0

I have the following script, designed to pass a variable from a Google Maps API v3 geocoded latitude and longitude to a haversine formula. However, each time it says that my geocoded vars "aren't defined":

var address = ['London'];

jQuery.each(address, function(index, item) {
  geocoder = new google.maps.Geocoder(); 
  geocoder.geocode( { 'address': item}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      startlat = results[0].geometry.location.lat();
      startlng = results[0].geometry.location.lng();
    } 
   });
  });

// start of haversine for marker distances
Number.prototype.toRad = function() {
   return this * Math.PI / 180;
};

var mlat = '50.1'; 
var mlng = '-1.05';  

var RDis = '3963'; // miles; Change to 6371 for km 
var x1 = mlat - startlat;
var dLat = x1.toRad();  
var x2 = mlng - startlng;
var dLon = x2.toRad();  
var aDis = Math.sin(dLat/2) * Math.sin(dLat/2) + 
                Math.cos(startlat.toRad()) * Math.cos(mlat.toRad()) * 
                Math.sin(dLon/2) * Math.sin(dLon/2);  
var cDis = 2 * Math.atan2(Math.sqrt(aDis), Math.sqrt(1-aDis)); 
var dDis = RDis * cDis; 
// dDis is the distance

Can anyone advise on how I can pass these through the script? Wrapping up the geocoding into the same function as the haversine isn't an option (I need to use each of them elsewhere, too).

Thanks for any help. :)

user1259798
  • 171
  • 1
  • 16

1 Answers1

0

The maps API call is asynchronous, so you can't use startlat and startlng until the callback occurs:

// ****** Moved this
// start of haversine for marker distances
Number.prototype.toRad = function() {
    return this * Math.PI / 180;
};

var address = ['London'];

jQuery.each(address, function(index, item) {
    geocoder = new google.maps.Geocoder();
    geocoder.geocode({
        'address': item
    }, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
            startlat = results[0].geometry.location.lat();
            startlng = results[0].geometry.location.lng();

            // ********* Moved block starts here *********
            var mlat = '50.1';
            var mlng = '-1.05';

            var RDis = '3963'; // miles; Change to 6371 for km 
            var x1 = mlat - startlat;
            var dLat = x1.toRad();
            var x2 = mlng - startlng;
            var dLon = x2.toRad();
            var aDis = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
                Math.cos(startlat.toRad()) * Math.cos(mlat.toRad()) *
                Math.sin(dLon / 2) * Math.sin(dLon / 2);
            var cDis = 2 * Math.atan2(Math.sqrt(aDis), Math.sqrt(1 - aDis));
            var dDis = RDis * cDis;
            // dDis is the distance
            // ********* Moved block ends here *********
        }
    });
});

More information in How to return the response from an asynchronous call?

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thanks for such a fast response, @T.J. Crowder. Would this mean that it calls the maps API call each time? The vars `mlat` and `mlng` are coming from an array (different part of the script), and so I would need to be able to store the `startlat` and `startlng` somewhere where it could be referenced repeatedly without making a unique call each time. Make sense? – user1259798 Mar 25 '15 at 08:35
  • @user1259798: You can store them and reuse them, but you can't use them the first time until after the callback has occurred, because you don't have them yet until then. – T.J. Crowder Mar 25 '15 at 08:48
  • Thank you so much for your answer, and sorry for being such a n00b on this. I’m struggling to understand how I can call something, and then reference it later? Can you explain how I would call my first function, and then reference the vars that are populated by that call in later functions? Sorry for needing so much schooling on this – I don’t understand the concepts well enough! – user1259798 Mar 26 '15 at 15:48