Google geocoding multiple addresses in a loop with javascript, how do I know when everything is done?

17,654

Solution 1

function someFunction(addresses, callback) {
    var coords = [];
    for(var i = 0; i < addresses.length; i++) {
        currAddress = addresses[i];
        var geocoder = new google.maps.Geocoder();
        if (geocoder) {
            geocoder.geocode({'address':currAddress}, function (results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    coords.push(results[0].geometry.location);
                    if(coords.length == addresses.length) {
                        if( typeof callback == 'function' ) {
                            callback();
                        }
                    }
                } 
                else {
                    throw('No results found: ' + status);
                }
            });
        }
     }
  }
}

//Usage
someFunction(addresses, function() {
    // Do something after getting done with Geocoding of multiple addresses
});

Use of Callback function is amazing

Solution 2

You could check if all calls have been finished by comparing the number of results to the number of addresses:

function someFunction(addresses) {
    var currAddress, coords = [];
    for (var i = 0; i < addresses.length; i++) {
        currAddress = addresses[i];
        var geocoder = new google.maps.Geocoder();
        if (geocoder) {
            geocoder.geocode({'address':currAddress}, function(results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    coords.push(results[0].geometry.location);

                    // Check if all calls have been processed
                    if (coords.length == addresses.length) {
                        someOtherFunction(coords);
                    }
                }
                ...
            });
        }
    }
}

function someOtherFunction(coords) {
    // Geocoding has been done for all addresses
    ...
}

Solution 3

If you are utilizing libraries such as jQuery, you could take advantage of Deferred Object to perform a chainable requests via geocoder.geocode function.

Example

function initMap() {
   
    var geocoder = new google.maps.Geocoder();

    var addreses = [
    { "lat": 60.173890, "lng": 24.941025 },
    { "lat": 60.461608, "lng": 22.266598 },
    { "lat": 61.498714, "lng": 23.760940 }
    ];

    var deferreds = getGeocodeAddressDeferred(geocoder,addreses);
    $.when.apply($, deferreds).done(function (locations) {

        //print results
        $.each(arguments, function (i, data) {
            $("div#result").append(data + "<br/>");
        });
    });
}
function getGeocodeAddressDeferred(geocoder, addreses) {
    var deferreds = [];
    
    $.each(addreses, function (i,address) {
        deferreds.push(geocodeAddress(geocoder, address));
    });

    return deferreds;
}

function geocodeAddress(geocoder, latLng) {
    var deferred = $.Deferred();
    geocoder.geocode({ 'location': latLng }, function (results, status) {
        if (status === google.maps.GeocoderStatus.OK) {
            deferred.resolve(results[0].formatted_address);
        } 
    });
    return deferred.promise();
}
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    <script src="https://maps.googleapis.com/maps/api/js?callback=initMap"
            async defer></script>
<div id="result"/>
Share:
17,654

Related videos on Youtube

user985219
Author by

user985219

Updated on June 04, 2022

Comments

  • user985219
    user985219 almost 2 years

    I've got a form that asks for a list of locations (not a lot, normally only 3 or 4 but that number is dynamic). When the form is submitted, I have to parse the data, use Google geocoding to get the locations, and then draw a line connecting the points in order. I have the parsing working, but I'm stuck on the geocoding part, mostly because of the asynchronous nature of it. Assume my address strings are stored in the array 'addresses', this is how far I've gotten:

    function someFunction(addresses) {
      var coords = [];
      for(var i = 0; i < addresses.length; i++) {
        currAddress = addresses[i];
        var geocoder = new google.maps.Geocoder();
        if (geocoder) {
          geocoder.geocode({'address':currAddress}, function (results, status)
            if (status == google.maps.GeocoderStatus.OK) {
              coords.push(results[0].geometry.location);
            } 
            else {
              throw('No results found: ' + status);
            }
          });
        }
      }
      // Initially I tried to work with the data here, but it wasn't all present yet.
    }
    

    Drawing the line is easy enough, I've done that before when users provided geographic lat/lng coordinates. My problem is, because the coordinates are only added in the callback, how do I know when it's done? I can't just dump that into a function and put in the callback because I need to wait until all the coordinates have been processed.

    I also read about someone who had issues with results not coming back in order but I didn't understand the provided response. If someone has an answer that can help me with my specific issue and ensure the results come back in order, I would greatly appreciate.

    NB: I hand-bombed that code, so there may be typos. My actual code thus far "works", I just don't know who to move from what I have to doing something once all addresses are processed. Also, this is currently being developed as an internal application for testing. Once testing is finished, it will comply fully with Google's TOS. This means I don't have a page I can link to. The entire application is also over 2,000 lines of code and contains some proprietary company information at this moment which will eventually be phased out, so pasting the entire thing or sending it out isn't feasible. I hope that doesn't pose too big a problem.