572

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
mauris
  • 42,982
  • 15
  • 99
  • 131
Gowri
  • 16,587
  • 26
  • 100
  • 160
  • 20
    Anyone who got here [**please read this question first**](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call). It explains how to tackle this problem effectively. – Benjamin Gruenbaum Aug 04 '14 at 10:57
  • **[Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference](http://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron)** also provides a more general, detailed explanation of the issue at hand. – Qantas 94 Heavy Feb 08 '15 at 03:05
  • 1
    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; '. :) – ISONecroMAn Aug 13 '16 at 14:41
  • use deasync like this https://stackoverflow.com/a/47051880/2083877 – Sunil Kumar Sep 08 '21 at 11:26

3 Answers3

554

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.

Sean Kinsey
  • 37,689
  • 7
  • 52
  • 71
  • 4
    :) 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. – Sean Kinsey Jul 27 '11 at 16:31
  • 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? – user2483724 Feb 21 '14 at 19:20
  • 2
    Upvote for finally making this make sense. – Steven Matthews Feb 13 '15 at 19:28
  • 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. – naneri Feb 26 '16 at 06:39
  • 6
    *"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. – nnnnnn Jul 07 '16 at 22:48
  • 4
    @Sean Kinsey,Can you tell me how to access location variable outside foo() function? – Yasin Patel Aug 29 '16 at 07:39
  • 1
    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... – Robert Sinclair Jun 27 '18 at 01:38
  • i was stuck in this async hole for long time, thank you :) – namila007 Jul 15 '18 at 21:48
  • For those of us in 2022 you can now use the [Promise API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) – fourk Jan 09 '22 at 13:58
  • @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. – César Rodriguez Apr 26 '22 at 21:16
  • Now how i will return `location` from `foo`? – Zeeshan Ahmad Khalil Nov 25 '22 at 09:53
  • How we will use location outside foo? – Rupal May 24 '23 at 07:09
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.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • 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. – César Rodriguez Apr 26 '22 at 21:27
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.

Alex Heyd
  • 1,323
  • 1
  • 10
  • 17