How to return value from an asynchronous callback function? [duplicate]
Asked Answered
S

3

577

This question is asked many times in SO. But still I can't get stuff.

I want to get some value from callback. Look at the script below for clarification.

function foo(address){

      // google map stuff
      geocoder.geocode( { 'address': address}, function(results, status) {
          results[0].geometry.location; // I want to return this value
      })

    }
    foo(); //result should be results[0].geometry.location; value

If I try to return that value just getting "undefined". I followed some ideas from SO, but still fails.

Those are:

function foo(address){
    var returnvalue;    
    geocoder.geocode( { 'address': address}, function(results, status) {
        returnvalue = results[0].geometry.location; 
    })
    return returnvalue; 
}
foo(); //still undefined
Stoned answered 27/7, 2011 at 16:12 Comment(4)
Anyone who got here please read this question first. It explains how to tackle this problem effectively.Wilding
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference also provides a more general, detailed explanation of the issue at hand.Spiderwort
Use Q, or any of it's variants, like $q library that comes with angularJs. And Never look back. Asynchronous functions immediately returns undefined. So never Waste your time trying do stuff on undefined. Also never use 'return' keyword in your async functions, as you normally do . Use deferred promises instead. deferred.resolve(STUFF you want to do) , then later you can simply return that ,'return deferred.promise; '. :)Sesame
use deasync like this https://mcmap.net/q/36126/-returning-a-value-from-callback-function-in-node-js-duplicateSchlenger
G
556

This is impossible as you cannot return from an asynchronous call inside a synchronous method.

In this case you need to pass a callback to foo that will receive the return value

function foo(address, fn){
  geocoder.geocode( { 'address': address}, function(results, status) {
     fn(results[0].geometry.location); 
  });
}

foo("address", function(location){
  alert(location); // this is where you get the return value
});

The thing is, if an inner function call is asynchronous, then all the functions 'wrapping' this call must also be asynchronous in order to 'return' a response.

If you have a lot of callbacks you might consider taking the plunge and use a promise library like Q.

Glad answered 27/7, 2011 at 16:15 Comment(12)
:) It's not strong, it's just how it is. As soon as you use an async method to pass data the entire function chain becomes asynchronous.Glad
If the chain of async functions manipulates an object, let's say a 'graph' object. Is there anyway I can get a reference to that object to call something like update() on it?Munniks
Upvote for finally making this make sense.Acolyte
Man, it helped me a lot. Was seeking for a solution for two days, everywhere so much info about that async, but no decent easy to understand examples.Squill
"you cannot use an asynchronous call inside a synchronous method." - Yes you can. You just can't use the async call's result from within the same synchronous method.Ayr
@Sean Kinsey,Can you tell me how to access location variable outside foo() function?Verlaverlee
Just so we're clear, this won't let you "return" the value of that variable in a way that PHP returns it. We're basically passing result of one callback function to another call back function. There's still no outside var that actually holds the result...Astronautics
i was stuck in this async hole for long time, thank you :)Trotyl
For those of us in 2022 you can now use the Promise APIKebab
@FourCinnamon0 No, the promise API doesn't change much. You will defer you answer for an assynchronous callback, and still won't be able to return the value.Iridis
Now how i will return location from foo?Purslane
How we will use location outside foo?Gaivn
O
34

It makes no sense to return values from a callback. Instead, do the "foo()" work you want to do inside your callback.

Asynchronous callbacks are invoked by the browser or by some framework like the Google geocoding library when events happen. There's no place for returned values to go. A callback function can return a value, in other words, but the code that calls the function won't pay attention to the return value.

Ondrea answered 27/7, 2011 at 16:13 Comment(1)
Yes, it makes fun sense to try and return a value from a promise callback. Unfortunately, it is not possible. For example, you may be crafting a class to scrape complex data from a website, and some data need to be retrieved through a http request. Using a fetch, you will never be able to make this class return an complex object with all the data (only using the blessed and deprecated xmlhttprequest). Using fetch, your class would need to mix different concerns and write the results into a database or other persisting method from inside the callbacks, according to the promises answers flow.Iridis
U
16

If you happen to be using jQuery, you might want to give this a shot: http://api.jquery.com/category/deferred-object/

It allows you to defer the execution of your callback function until the ajax request (or any async operation) is completed. This can also be used to call a callback once several ajax requests have all completed.

Ultimate answered 27/7, 2011 at 17:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.