1

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

Community
  • 1
  • 1
Niraj Pandkar
  • 163
  • 4
  • 15

2 Answers2

1

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);
    }
}
Paarth
  • 9,687
  • 4
  • 27
  • 36
  • Thanks for answering! But is there any way around to make this code work or I'll have to resort to promise.js to do the work? Also I have seen in the links I posted above, that they have managed to do the same thing and got it working. So how's that possible here? – Niraj Pandkar May 10 '16 at 06:30
  • You totally can, but you have to get away from the idea of "returning" something if you're using callbacks. It can't really be done. You can only forward the variable onto another callback. – Paarth May 10 '16 at 06:33
  • Though in this case as Jose says your module syntax is funky. You're going to have to call it externally and pass in a callback that uses the value. – Paarth May 10 '16 at 06:34
  • Could you elaborate on "call it externally and pass in a callback that uses the value"? Thanks for the additional information. – Niraj Pandkar May 10 '16 at 06:54
  • Sure, so recently Javascript's gotten a standardized module system that defines the scope of what's visible and what's not. It seems like the module that you've written in your question is meant to be treated as a library and not as an entry point to an application. If it's meant to be treated as a library, that means you don't have all the information you'd need to make decisions and so you'll need to allow someone else to pass in a callback -- which you're already doing in foo. So rather than trying to *call* foo in your module.exports block, export it directly and call it elsewhere. – Paarth May 10 '16 at 06:57
  • @NirajPandkar though I believe right now the existence of the module.exports may be distracting from the actual issue. – Paarth May 10 '16 at 06:58
  • @NirajPandkar I updated my answer with some more details. Does that help at all? – Paarth May 10 '16 at 07:04
  • Exactly! You guessed it right. I am making a library. So I should `module.exports = foo()` . But I don't have anywhere to use it.. Sorry this is my first encounter with modules in javascript. I think now I am on the right track but still not there yet. Edit: Your edit and comments weren't loaded when I was writing this comment. Sorry will look into it – Niraj Pandkar May 10 '16 at 07:12
  • @NirajPandkar as a reminder, `foo()` calls the function, `foo` is the function itself. You want to export the function itself, not execution. – Paarth May 10 '16 at 07:15
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/111541/discussion-between-niraj-pandkar-and-paarth). – Niraj Pandkar May 10 '16 at 14:18
  • Hey sorry to bother you again. But still not able to achieve what I want. As a last resort should I just post a github link so that you could look into the situation personally? Is that okay with you? – Niraj Pandkar May 12 '16 at 18:04
  • You can do that, but posting a fiddle may be preferable so its self contained. We could also go back to the chat. – Paarth May 12 '16 at 19:07
  • Lost the privilege to chat because of the downvote on the question. https://jsfiddle.net/sh7ey5jc/1/ There's no html involved in the library building but I didn't know how else to output the value. Also could you suggest some way we could take this conversation off SO. – Niraj Pandkar May 13 '16 at 06:51
1

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 */});
Jose Hermosilla Rodrigo
  • 3,513
  • 6
  • 22
  • 38
  • Thanks for replying! Could you elaborate a little more using the code because I don't get how module.exports = foo; is different than what I did and how will it change the execution? I am referring to - http://www.sitepoint.com/understanding-module-exports-exports-node-js/ – Niraj Pandkar May 10 '16 at 06:43
  • That's another way to put it, but the problem is I want to `return` my result which is not possible as stated by Paarth. So the body of foo where you have mentioned `//your result here`, I really can't return the result from there, can I? – Niraj Pandkar May 10 '16 at 14:12
  • No, if you mean with return to assign the variable result to another variable, that's not possible. Maybe promisifying the function but I don't really know yet how to do it correctly. But there's no reason to return, simply do whatever you want to do inside the callback body where it says //your result is here, or is there a reason to return? – Jose Hermosilla Rodrigo May 10 '16 at 14:25
  • Yes.. Actually I am trying to make a library and have to return values when user calls certain functions. I guess I will look into promise.js to get my work done. – Niraj Pandkar May 10 '16 at 14:31