-1

So I have an array of objects with the following properties: Address, Latitude, Longitude, and Title

 poi("139 Main St", 0, 0, "Farmer's Market" ),
 poi("18 N Hopkins Ave", 37.4455, -143.7728, "YMCA" ),
 poi("42 Universe St", 37.4855, -143.8781, "Original Pizza #32" )

Now, the first object does not have anything set for latitude and longitude, so I was hoping to use Google's Geocode API to fill in the missing data. I included the API script link with my API key, which is working fine.

I then created a for loop that goes through the array and finds any object with missing data. It's supposed to go through and replace any empty cells with the correct information. However, though the information is retrieved, it does so after the loop is completed. I can console out the correct information, but only after the function returns empty data.

for (i=0; i < poiArray.length; i++ ) {
    var curr = poiArray[i];

    if ( !curr.lat || !curr.long ) {

        geocoder = new google.maps.Geocoder();
        geocoder.geocode( { 'address': curr.address }, function(results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
                cur.lat = results[0].geometry.location.k;
                cur.long = results[0].geometry.location.B;
            } else {
                console.log('failed to include ' + curr.title);
                poiArray.splice(i--, 1);    
            }

       });  

    }

}

I've tried timeout and nesting functions, but nothing seems to work. Any suggestions?


Let me mention a bit more weirdness: if I console after if (status == google.maps.GeocoderStatus.OK) { the variable i in my for loop, I get the last number of my array... every time. And the loop only seems to update the last item in my array if I console my poiArray after the asynchronous data from Google has loaded.

geocodezip
  • 158,664
  • 13
  • 220
  • 245
invot
  • 533
  • 7
  • 30
  • 2
    After the information is logged to the console can you check the poiArray and see if it has been updated? while the for loop may have already finished, I *think* the variable should be updated. Is the problem that the rest of your code starts running even thought the data is not yet updated? – wolffer-east Jul 22 '14 at 17:37
  • 1
    The geocoder is asynchronous. The results come back from the server when they come back from the server. You can solve your issue with function closure. – geocodezip Jul 22 '14 at 17:42
  • 1
    You're making an **asynchronous** request - by the time you have reached the end of the current loop iteration, the data is not yet available to you which is the entire purpose of the callback function. This is a good read for you - http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call. – Adam Jenkins Jul 22 '14 at 17:43
  • Why is this question being down-voted? This brought up some really interesting points. – invot Jul 22 '14 at 17:58

1 Answers1

2

you can solve your issue with function closure. Also, you shouldn't use undocumented properties of the Google Maps Javascript API v3 (.k, .B), they will change with updates of the API and break your code.

var geocoder = new google.maps.Geocoder();
function geocodeAddress(curr, i) {
  geocoder.geocode( { 'address': curr.address }, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
       cur.lat = results[0].geometry.location.lat();
       cur.long = results[0].geometry.location.lng();
    } else {
       console.log('failed to include ' + curr.title);
       poiArray.splice(i--, 1);    
    }
  });  
}
for (i=0; i < poiArray.length; i++ ) {
    var curr = poiArray[i];
    if ( !curr.lat || !curr.long ) {
        geocodeAddress(curr, i);
    }
}
geocodezip
  • 158,664
  • 13
  • 220
  • 245
  • 1
    Will this require the function to finish the geocode call before moving on to the next iteration of the for loop? If so it could bog down the code with a fairly small number of calls – wolffer-east Jul 22 '14 at 17:51
  • Brilliance. This worked perfectly and shows exactly where I played the fool. Thank you for pointing out the .k .B issue as well. – invot Jul 22 '14 at 17:53
  • @wolffer-east: The end-user will not be executing this script. Admin will only run it once in a blue moon. Does it matter then if it is a little intensive in that instance? – invot Jul 22 '14 at 17:56
  • 1
    @invot If it is in the backend you should be good to go. Im not event certain what the lag would be, and would only be worried if it was firing onload/doc ready – wolffer-east Jul 22 '14 at 17:59