问题
I'm having a trouble with assigning return value from Firebase call function to my global variable. This is my function:
function getThePushNameById( path , id ){
path.once( 'value', function( data ){
if( data.child('id').val() != id ){
data.forEach( function( newData ){
var base = new Firebase( path.child( newData.name() ).toString() );
getThePushNameById( base, id );
})
}else{
//finishes the function when path is founded - returns the value
return path.name();
}
})
}
and this is the other file where I set the request:
var base = new Firebase(path/to/my/base);
var output = getThePushNameById( base , 2 )
console.log(output);
So my problem is that console.log doesn't wait for output to be defined, but runs itself and logs undefined. And my question is if someone knows how can I make console.log wait for value?
回答1:
Welcome to asynchronous programming in JavaScript.
When we look at your main code:
var output = getThePushNameById( base , 2 )
console.log(output);
Then you (logically) assume that the getThePushNameById will have completed before the console.log statement is executed.
Unfortunately that assumption is false when we are programming against a server. In your case getThePushNameById reaches out to Firebase, which may take a long time to complete. If the browser would simply wait for the call to complete, the entire application would be blocked.
Instead of blocking the application, the browser spins off the call-to-the-server into a background activity. And you pass in a function that it will call when the background activity is completed. It's like when you sign up for delivery notifications from FedEx. Instead of having to check at the front door if the package is already there, you receive a text message when the package has been dropped off.
This spawn-background-work-that-calls-you-back-when-it-has-completed approach is essential to most of the modern web. You're best of embracing it early on and not trying to work against it.
In your case you can embrace it, by passing in a callback function into you getThePushNameById and calling that function when you receive the value from Firebase:
function getThePushNameById( path , id, callback ){
path.once( 'value', function( data ){
if( data.child('id').val() != id ){
data.forEach( function( newData ){
var base = new Firebase( path.child( newData.name() ).toString() );
getThePushNameById( base, id, callback );
})
}else{
//finishes the function when path is founded - returns the value
callback(path.name());
}
})
}
getThePushNameById( base, 2, function(output) {
console.log(output);
});
回答2:
function getThePushNameById( path , id, callback ){
path.once( 'value', function( data ){
if( data.child('id').val() != id ){
data.forEach( function( newData ){
var base = new Firebase( path.child( newData.name() ).toString() );
getThePushNameById( base, id , callback ); //here was the error
})
}else{
//finishes the function when path is founded - returns the value
callback(path.name());
}
})
}
getThePushNameById( base, 2, function(output) {
console.log(output);
});
founded an error: callback was not back defined when function called itself again, so it returned an undefined. this code is now ok and works well
来源:https://stackoverflow.com/questions/25697907/javascript-assigning-value-to-variable-from-callback-return-timing