1

I am trying to create a function to return a lat/long array from the Google Maps JS API (v3). I am able to write the data out that I retrieve from the API, but I am not able to pass the data along to a variable. I am wanting to do something like this:

var latLong = getLatLong(Address);

The function that I have created is here:

function getLatLong(loc, callback) {
  var geocoder = new google.maps.Geocoder();
  var array = new Array();

  if (geocoder) {
    geocoder.geocode({ 'address': loc }, function (results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
        var latLng = results[0].geometry.location;;
        $.each(latLng, function(k, v) {
          if (k == 'va' || k == 'wa') {
            array.push(v);
          }
        });
        var ret = array;
        callback(ret);
      } else {
        console.log("Geocoding failed: " + status);
      }
    });
  }
}

I then am assigning the function to a variable and calling it to give me the lat/long.

var geo = getLatLong('Dallas, TX', function(result) {
  return result;
});

Unfortunately this produces an 'undefined' result. I can access the result in the function, I just can't pass it along. How can I pass the result of the function to a variable to be accessed?

1
  • did you mean you need a return somewere? Commented Nov 30, 2010 at 0:40

4 Answers 4

3

Unfortunately this produces an 'undefined' result

Do you mean in the 'geo' variable? If so, you are missing the point of callbacks. The function you pass in will be called later after the getLatLong() call returns. Callbacks are asynchronous functions, and you will want to use the callback to take an action (e.g. change state, tweak a display, etc.) of your choice.

Try changing it to

function(result) { alert('callback result: '+result); }

to check if it gets called properly. If you get an alert() properly, then you might want to do something like this:

var geo = null;
getLatLong('Dallas, TX', function(result) {
   // cache state
   geo = result;
   // do something with it
   showResultInSomeSpotOnThePage(result);
});
/* We can't use the "geo" variable contents immediately
 * after getLatLong returns; it will be set at some time later.
 * But there may be some use for keeping the result around indefinitely,
 * we just have to be prepared for "geo" to be null if we check it
 * before the callback is called.
 */
Sign up to request clarification or add additional context in comments.

4 Comments

well said. clear example. the comment at the end of your example is key. +1
The callback I was using was the result of my frustration in trying to return the lat/long to a variable. I was trying to be creative! :-)
TThanks for the great example! My thought was that there should be some way to return the result to a variable. I guess I'm just going to have to use a callback to do what I'm wanting.
@Jason: You can store the result in a variable, it's just that to do so directly via your getLatLong function's return value, you'd have to block = busy-wait, and that's either bad form (if the Javascript interpreter is multithreaded) or impossible (if it's single-threaded). Asynchronous calls just take some getting used to. It's a common idiom in Javascript; see setInterval or setTimeout. (and start to learn about closures)
3

You can't structure the code the way you want to here. The problem is that geocoder.geocode() is an asynchronous operation. That's why it takes a callback function. When you call geocoder.geocode(), it initiates the request to fetch the geocode, and then returns, leaving the request running in the background. When the request eventually completes, google's api will execute the anonymous function you passed as the second parameter to geocode().

So when you call getLatLong() the actual order that things happen is something like this:

  1. call geocoder.geocode(). (initiates geocode request)
  2. getLatLong() is done and returns undefined. (this is where geo gets set)
  3. (the geocode request completes) google api calls the anonymous function, which pushes the LatLng values into array, and then calls your callback()

to better visualize what's going on, you might write your code as follows (this is exactly equivalent to the way you've written it):

function getLatLong(loc, callback) {
  var geocoder = new google.maps.Geocoder();
  var array = new Array();

  function handleGeocodeResponse(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      var latLng = results[0].geometry.location;;
      $.each(latLng, function(k, v) {
        if (k == 'va' || k == 'wa') {
          array.push(v);
        }
      });
      var ret = array;
      callback(ret);
    }
  }

  if (geocoder) {
    geocoder.geocode({ 'address': loc }, handleGeocodeResponse);
  } else {
    console.log("Geocoding failed: " + status);
  }

  // note- no return specified explicitly is the same as
  //return undefined;
}

So, if you can't return a value, then how do you use the results? Like this:

getLatLong('Dallas, TX', function(geo) {
  // geo is passed to this function as a parameter
  // move all code that requires `geo` into this function.

});

1 Comment

I really like the way you defined the order of events. I was thinking there would be a way to return the results to a variable in some fashion. Due to the asynchronous nature of the call, I can see that's not going to be possible. I'm just going to do the callback and let that function work it's magic. Thanks for the help!
1

The key point here is that getLatLong doesn't return a value. That is why geo is always undefined.

To make this work, you'll need to modify your callback function. Something like this:

getLatLong('Dallas, TX', function(result)
{
    var geo = result; 
    //continue to use geo here as you normally would
});

3 Comments

getLatLong can't return a value unless either google's geocoder.geocode returns a value, or there is a blocking (=bad!) call to await geocoder.geocode's completion.
The key issue is actually the asynchronous nature of the geocode call, your examples suggest that geo will contain a usable value immediately following the call to getLatLong() ... which is not true at all. As a result, this confuses the issue further, rather than clarifying it.
Ok thanks for the feedback guys, you've helped me understand this much better! I've removed the inaccurate parts of my answer. +1 for both :)
0

geo is undefined because getLatLong() doesn't return anything (which means it returns undefined).

3 Comments

so you probably want to write "return callback(ret);" in getLatLong()
he can't return callback(ret) since ret is not obtained until Google's geocoder API calls the callback.
yes, but the core issue is that the asynchronous result of geocoder.geocode(), can't be returned synchronously from the OP's getLatLong() function.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.