Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

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.

like image 492
Muffasa Avatar asked May 15 '26 20:05

Muffasa


1 Answers

If you add a few console.log statements, you'll be able to see how your code flows:

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. This is because on starts an asynchronous load of the data from 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. But by then, the original context has finished.

There is no way in JavaScript to wait for an asynchronous function to finish. 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.

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.

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);
like image 59
Frank van Puffelen Avatar answered May 18 '26 08:05

Frank van Puffelen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!