0

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?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
maticzav
  • 880
  • 9
  • 17

2 Answers2

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);
});
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • why is my bug reporter reporting [Error] TypeError: undefined is not a function (evaluating 'callback(path.name)') if i paste same code into mine? – maticzav Sep 06 '14 at 16:10
  • Unfortunately I can't debug your application for you. I recommend setting a breakpoint on this line `callback(path.name());` and seeing what happens. – Frank van Puffelen Sep 06 '14 at 16:21
  • 1
    i found it! it was my bad in code when the function called itself again. Callback wasn't defined – maticzav Sep 06 '14 at 18:11
0
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

maticzav
  • 880
  • 9
  • 17