0

I am trying to return value from function inside function in a nodejs app. Its always coming out to be undefined.

var geo = {
    list: function(callback){
        var returnval;
        gapi.getcodes(function(error, data) {
            if (error) {
               console.log(error);
             } else {
               returnval = data; 
               console.log(returnval);
            }                        
        });
        callback(returnval);                
      }            
}

var geocodes = geo.list(function(){});
console.log("Value of geocodes: "+geocodes);

I know gapi.getcodes is asynchronous function and i read on another thread that I should be passing callback function to get the return value. But still the value of geocodes is still coming out to be undefined.

When the code runs i see the value returned in

console.log(returnval)

. How do I get this value to be stored in a var?

I am not sure what is wrong. Please help I am trying to learn javascript and object style pattern.

3
  • Please indent your code properly. It makes it very hard to see what is what when you have errant indentation. Commented Feb 18, 2015 at 5:19
  • you can make use of promises as well. Commented Feb 18, 2015 at 5:24
  • sorry about that I have fixed that... :| Commented Feb 18, 2015 at 5:36

2 Answers 2

4

geo.list() does NOT return your answer. In fact, that function doesn't return anything so geocodes will just be undefined the way you had it.

Instead, geo.list() needs to be modified so it passes the data value to the callback as an argument because only when the asynchronous getcodes callback is called sometime in the future is the data actually available.

So, you can use it like this by consuming the result in the callback function itself (that's what it is for):

var geo = {
    list: function(callback){
        gapi.getcodes(function(error, data) {
            if (error) {
                callback(error);
            } else {
                callback(null, data);
            }                        
        });
      }            
}

geo.list(function(err, geocodes){
    // because the result here is asynchronous, you can ONLY use it
    // in this callback or in any function you pass it to from here
    if (!err) {
        console.log("Value of geocodes: "+geocodes);
    }
});

Actually, it can be done even simpler:

var geo = {
    list: function(callback){
        gapi.getcodes(callback);               
      }            
}

geo.list(function(err, geocodes){
    // because the result here is asynchronous, you can ONLY use it
    // in this callback or in any function you pass it to from here
    if (!err) {
        console.log("Value of geocodes: "+geocodes);
    }
});

But, with this simpler implementation, you can see that the geo object isn't really adding any value at all as it's just copying an existing API without adding any extra functionality.

Sign up to request clarification or add additional context in comments.

5 Comments

How do i save it to a var ? If i do var geocodes =geo.list(function(err, geocodes){}); and do a console.log(geocodes) in next line it says geocodes is not defined.
@maths - please read and study my answer again. This function is asynchronous and you simply can't do what you're trying to do. Can't ever do it that way. To use asynchronous operations in Javascript, you HAVE to learn how to code for asynchronous results. You cannot just program in a synchronous fashion. You can use the results ONLY in the callback.
ok so to make asynchronous funcs run in sequence i will have to make callbacks in callbacks
@maths - yes, or use promises which help manage that for you.
just an update, I used promise q library in my app and working with asyncs was a breeze... thanks cheers!
0

You're calling the callback provided to list outside of the getcodes() callback, and attempting to use returnval before it's even set. As getcodes() is asynchronous.

Move callback(returnval) inside the anonymous function passed to getcodes(). Like so:

var geo = {
    list: function(callback){
        var returnval;
        gapi.getcodes(function(error, data) {
            if (error) {
                console.log(error);
            } else {
                returnval = data; 
                console.log(returnval);
               }                        
            }
            callback(returnval); // <-- here
        );
        callback(returnval); // <-- instead of here
      }            
}

geo.list(function(geocodes) {
    console.log("Value of geocodes: " + geocodes);
});

Alternatively it could be as simple as:

var geo = {
    list: gapi.getcodes.bind(gapi)
};

geo.list(function(err, geocodes) {
    if (!err) {
        console.log("Value of geocodes: " + geocodes);
    }
});

I personally prefer to work with promises than callbacks, here is what that would look like using a promise library such as bluebird:

/** assuming bluebird is included **/
var gapiAsync = bluebird.promisifyAll(gapi);

var geo = {
    list: gapiAsync.getcodesAsync.bind(gapiAsync)
};

geo.list.then(function(geocodes) {
  console.log(geocodes);
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.