简体   繁体   中英

Proper javascript functions structure

I'm getting data from my firebase

//user balance check
var balanceRef = new      Firebase('https://****.firebaseIO.com/arcade/grabbit/'+category+'/'+brand+'/'+gameId+'/'+'activePlayers'+'/'+userId+'/');

Here's the function that gets the data

//check user balance
function checkBalance(){
balanceRef.on('value', function(snapshot) {
if(snapshot.val()=== null){
  mLeft=0
 } else{
 mLeft=snapshot.val().tokensLeft
        }
 return mLeft 
                             })
 }

When the user clicks a button I 1st check their balance

$('#grabbit').click(function() {

 //call checkBalance function on click
 var myTokensLeft=checkBalance();

 });

the problem here is it's returning the function value as NaN or undefined

I've tested repeated, the function does return a value. Why can't It pick up the value on click? Am I doing something wrong with the structure. I'm very new to javascript

balanceRef.on looks like an async function to me, which is why you won't get a return value. try something like this:

//check user balance
function checkBalance(callback){
  balanceRef.on('value', function(snapshot) {
    if(snapshot.val()=== null){
      mLeft=0
    } else{
      mLeft=snapshot.val().tokensLeft
    }
    callback(mLeft);
  })
}


$('#grabbit').click(function() {

  //call checkBalance function on click
  checkBalance(function(myTokensLeft){

  // do something with myTokensLeft

  });   

});

EDIT: more details

the function balanceRef.on does not return your desired data, it only attaches the function function(snapshot)... to the object balanceRef 's value event. When the object balanceRef 's value event gets triggered (ie data is available), your function function(snapshot)... gets executed, but it's return values goes nowhere, because the javascript parser has already moved on.

try this:

function checkBalance(){
  balanceRef.on('value', function(snapshot){
    return 'foo';
  });  
  return 'bar';
}

$('#grabbit').click(function(){

  console.log(checkBalance());
  // this will print 'bar' in your
  // in your console, not 'foo'
});

EDIT 2: to avoid callback chaining, one can use a variable that will be common to both functions. (not a very good practice though, since you cannot be sure that the value has been set, when you want it!)

(function(){
  // added the closure to avoid myTokensLeft cluttering 
  // into global variables

  var myTokensLeft;

  balanceRef.on('value', function(snapshot){
    var mLeft;
    if (snapshot.val()=== null){
      mLeft=0
    } else{
      mLeft=snapshot.val().tokensLeft
    }
    myTokensLeft = mLeft;
  });

  $('#grabbit').click(function(){

    // do something with myTokensLeft

  });

}());

It seems to me that on your click event you only create another listener to "value" event and gods know how and when that event is triggered and where the function returns your mLeft.

What is happening in your code is that after each click on "#grabit" always new listener is created, but the function inside is not necessarily to be called and if it is called it is called asynchronously which means by the time it is finished you already got "undefined".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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