有什么办法可以破坏匿名函数中的 Javascript 函数吗?

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

我只想检查我要插入的数据是否已经存在于我的 Firebase 中,如果存在,我只想破坏添加功能:

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;
       }
   });

};

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

来自 Firebase 文档,snapshot.forEach returns true 如果您的回调函数 "cancels the enumeration by returning true"。所以只需将 return false 更改为 return true!

forEach 循环中设置一个 "global" (给你的 addCampaign 函数)标志,然后在退出它之前检查这个标志,然后当你回到你的主函数时检查这个标志和 return 如果已设置。

如果您添加一些 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. 之后立即触发,而 1. 位于代码块的开头。这是因为 on 开始从 Firebase 异步加载数据。由于这需要时间,因此浏览器会继续执行该块之后的代码。从 Firebase 的服务器下载数据后,它会调用回调,你可以做你想做的事。但是到那时,原始上下文已经完成了。

JavaScript 中无法等待异步函数完成。如果存在这样的方式,您可能会很感激,但您的用户会因为他们的浏览器在您对 Firebase 的调用结束时锁定而感到沮丧。

相反,您有两个选择:

  1. 将回调传递给函数
  2. return一个承诺

我将使用下面的选项 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);