Niraj Pandkar
Niraj Pandkar

Reputation: 173

Not able to return value even with callback function

I have read the following questions and corresponding insightful answers and understood how asynchronous call back functions work-

How do I return the response from an asynchronous call?

How to return value from an asynchronous callback function?

Returning value from asynchronous JavaScript method?

But still not able to successfully return the appropriate vaule. Following is the code -

function foo(callback){
    request('some-url.json', function (error, response, body) {
        //Check for error
        if(error){
            //error body
        }

        //Check for right status code
        if(response.statusCode !== 200){
            //response body
        }

        //All is good. Print the data
        var data = JSON.parse(body);
        callback(data.some-property);
    });
}


module.exports = {
    foo:foo(function(result){
        console.log(result); //works
        return result; //doesn't work

    }),
};

I am able to get the expected result in the console log but still its not able to return the value.

Error: TypeError: Property 'foo' of object #<Object> is not a function

Problem:

1.Is the callback function execution correct?

2.What should I do to return the value successfully?

Edit: Finally after an extensive conversation with Paarth I have decided to resort to promise.js which will allow me to indirectly return the value I seek from my function. For further resources regarding promise.js -

https://gist.github.com/domenic/3889970

https://www.promisejs.org/

http://colintoh.com/blog/staying-sane-with-asynchronous-programming-promises-and-generators

Also worth mentioning : Bluebird & q

Upvotes: 1

Views: 2216

Answers (2)

Jose Hermosilla Rodrigo
Jose Hermosilla Rodrigo

Reputation: 3683

That's because module.exports won't wait to the request (asynchronous) to finish. Simply export the function and call it somwhere when you want.

You can export the function :

//yourController.js
module.exports = foo;

Now require that function somewhere in other file and call it :

// another.js
var foo = require('yourController.js');
foo(function(result){
  // your result is here
});

Or

require('yourController.js')(function(result){/* Do whatever with result */});

Upvotes: 1

Paarth
Paarth

Reputation: 10377

There's no real way to go from asynchronous code back to synchronous code. You can get close by using promises which treat delayed operations as data so you can return the promise object and set up actions that will happen on it later, but with callbacks you have to just keep creating callbacks.

You can find some basic information on promises here https://www.promisejs.org/ (though I'm not endorsing promise.js) and more here.

If you're working in ES5 Bluebird and Q are well known promise libraries. Promises are native functionality in ES6.


So ignoring the module syntax let's say you're trying to use that function.

function something() {
    ...
    // result not bound, foo is not called
    foo(function(result){

        console.log(result); //result was passed into this callback and is bound

        return result; //result is still bound but returning does nothing. No one is waiting for the return value.
    });
    // code below this point probably already executed before your console.log in the foo callback. No one is waiting for the return.
}

Responding directly to your questions:

  1. Yes, you called foo correctly until you tried to return something. Returning isn't really a concept that applies to callback functions. You can only pass the data on to other callbacks.

  2. You don't ever return the value.

Let's say I have foo, which takes in a callback. If I want to act on foo's result in another function, foo2, I have to call

function foo2 () {
    foo(function(result) { 
        //act on result 
    }
}

Now let's say I want foo2 to return foo1's result to yet another function. Well, with callbacks, I can't. I can only ask foo2 to take in yet another callback and pass on the data.

function foo2 (callback) {
    foo(function(result) { 
        callback(result);
    }
}

Upvotes: 1

Related Questions