有没有办法破坏匿名函数中的 Javascript 函数

Is there any way to break Javascript function within an anonymous function?

本文关键字:函数 Javascript 有没有      更新时间:2023-09-26

我只想检查我要插入的所有就绪数据是否存在于我的Firebase上,如果是这样,我只想破坏add函数:

FBDB.addCampain=function (campain){
        CampiansRef.once('value',function(snapshot){
        snapshot.forEach(function(childSnapshot){
           if(campain.Name==childSnapshot.val().Name){
               console.log("campain allredy exists on the DB");
              return false; //I want to break the addCampain function from here!
           }
         });
        });
   var newCampainRef =  CampiansRef.push();
   campain.id = newCampainRef.key();
   newCampainRef.set(campain,function(error){
       if(error){
           console.log("an error occured the campain did not add to the DB, error:" ,+error);
           return false;
       }
       else{
           console.log("campain succssesfuly added to the DB");
           return true;
       }
   });
};

目前发生的情况是,即使活动存在于数据库中,它仍然继续实际添加代码。必须有一种方法可以在其中的匿名函数中"破坏"addCampain函数,甚至将"return false"传递到主范围。

如果添加一些console.log语句,您将能够看到代码的流动方式:

console.log('1. starting call to Firebase');
CampaignsRef.once('value',function(snapshot){
    console.log('3. for value from Firebase');
    snapshot.forEach(function(childSnapshot){
        console.log('4. inside childSnapshot');
        if (campaign.Name==childSnapshot.val().Name){
            console.log("campaign already exists on the DB");
            return false;
        }
        console.log('5. done with snapshot.forEach');
    });
});
console.log('2. we started the call to Firebase');

输出将如下所示:

1. starting call to Firebase
2. we started the call to Firebase
3. for value from Firebase
4. inside childSnapshot
4. inside childSnapshot
4. inside childSnapshot
5. done with snapshot.forEach

这可能不完全是您所期望的。 2. 位于代码块的末尾,但它在1.之后立即触发,即在开始时。这是因为on会从 Firebase 异步加载数据。由于这需要时间,浏览器在块后继续使用代码。从Firebase的服务器下载数据后,它将调用回调,您可以执行所需的操作。但到那时,原始上下文已经结束。

JavaScript 中没有办法等待异步函数完成。虽然如果存在这种方式,您可能会感激,但您的用户会对以下事实感到沮丧:当您对 Firebase 的调用停止时,他们的浏览器被锁定。

相反,您有两种选择:

  1. 将回调传递到函数中
  2. 返回承诺

我将使用下面的选项 1,因为这是 Firebase JavaScript SDK 已经执行的操作。

FBDB.addCampaign=function (campaign, callback){
    CampaignsRef.once('value',function(snapshot){
        var isExisting = snapshot.forEach(function(childSnapshot){
            if(campaign.Name==childSnapshot.val().Name){
                return true; // this cancels the enumeration and returns true to indicate the campaign already exists
            }
        });
        callback(isExisting);
    });
};

你可以像这样调用它:

FB.addCampaign(campaign, function(isExisting) {
    console.log(isExisting ? 'The campaign already existed' : 'The campaign was added');
};

请注意,从服务器加载所有广告系列以检查特定的广告系列名称是否已存在是非常浪费的。如果您希望广告系列名称是唯一的,则不妨按名称存储广告系列。

CampaignsRef.child(campaign.Name).set(campaign);

根据 Firebase 文档,如果您的回调函数"通过返回 true 取消枚举",snapshot.forEach 返回true。因此,只需将您的return false更改为return true

forEach循环中设置一个"全局"(到你的addCampaign函数(标志,然后在你回到主函数时检查这个标志,如果设置了,则返回。