简体   繁体   English

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

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

I just want to check if the data I'm about to insert allready exists on my Firebase, and if so I just want to break the add function: 我只想检查我即将在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;
       }
   });

};

What currently happens is that even if the campaign exists on the database it still continues to the actual adding code. 当前发生的情况是,即使活动存在于数据库中,它仍会继续执行实际的添加代码。 There must be a way to "break" the addCampain function within an anonymous function inside it, or even pass the "return false" up to the main scope. 必须有一种方法可以“破坏”其内部匿名函数中的addCampain函数,甚至可以将“ return false”传递给主作用域。

If you add a few console.log statements, you'll be able to see how your code flows: 如果添加一些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');

The output will look like: 输出将如下所示:

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

This is probably not entirely what you expected. 这可能不完全是您所期望的。 2. is at the end of the code block, but it fires right after 1. which is at the start. 2.在代码块的末尾,但是它在开始的1.之后立即触发。 This is because on starts an asynchronous load of the data from Firebase. 这是因为on从Firebase开始异步加载数据。 And since this takes time, the browser continues with the code after the block. 并且由于这需要时间,因此浏览器在该块之后继续执行代码。 Once the data is downloaded from Firebase's servers, it will invoke the callback and you can do what you want. 从Firebase的服务器下载数据后,它将调用回调,您可以执行所需的操作。 But by then, the original context has finished. 但是到那时,原始上下文已经完成。

There is no way in JavaScript to wait for an asynchronous function to finish. JavaScript中没有办法等待异步函数完成。 While you might appreciate if such a way existed, your users would be frustrated by the fact that their browser locks up while your call to Firebase is out. 尽管您可能会喜欢这种方法,但您对用户的失望是,在您对Firebase的呼叫中断时,他们的浏览器锁定了。

Instead you have two options: 相反,您有两个选择:

  1. pass a callback into the function 将回调传递给函数
  2. return a promise 兑现承诺

I'm going to use option 1 below, because it is what the Firebase JavaScript SDK already does. 我将使用下面的选项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);
    });
};

You'd invoke this like: 您可以像这样调用它:

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

Note that loading all campaigns from the server to check if a specific campaign name already exists is pretty wasteful. 请注意,从服务器加载所有活动以检查特定的活动名称是否已经存在非常浪费。 If you want campaign names to be unique, you might as well store the campaigns by name. 如果您希望广告系列名称唯一,则最好按名称存储广告系列。

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

From the Firebase documentation, snapshot.forEach returns true if your callback function "cancels the enumeration by returning true ". 从Firebase文档中,如果您的回调函数“通过返回true取消枚举”,则snapshot.forEach返回true So just change your return false to return true ! 因此,只需将return false更改为return true

在中断之前,在forEach循环中设置一个“全局”(对addCampaign函数)标志,然后在返回主函数并返回是否已设置时检查此标志。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM