devoncrazylegs devoncrazylegs - 1 month ago 12
Javascript Question

Adding a promise to a Google Maps API call

I need to return an array from a function in Javascript/jQuery but the function is returning before the array has been set (as it is an AJAX call).

I have been advised to use a promise but I have not used these before and have so far been unable to implement this into my code. Here is my code:

mapClass.setLatLng = function(location, clubs) {
document.geoCodeRequestCompleteFlag = 0;
geocoder = new google.maps.Geocoder();
geocoder.geocode({'address' : location}, function(results, status) {
//console.log(results);
if(status === "OK") {
var latLngArray = [];
latLngArray.push(parseFloat(results[0].geometry.location.lat()));
latLngArray.push(parseFloat(results[0].geometry.location.lng()));
var sortedArray = mapClass.calculateDistances(clubs, latLngArray);
return sortedArray;
}
});
}


As you can see, the sortedArray variable is empty when I return is. Does anyone have any ideas as to how I could add blocking code into this to ensure the array variables are set before returning?
Thanks

Answer

The way you use promises is that you create a promise and then return that promise from your method. This promise has methods like .then(successHandler, errorHandler) that enable you to specify functions to execute when the promise is resolved (is given a value). You then resolve the promise when you get back the results from the geocoder call at some point in the future.

In jQuery, the promises are called Deferreds.

Your code would then change to something like this:

mapClass.setLatLng = function(location, clubs) {
        var deferred = $.Deferred(),
            geocoder = new google.maps.Geocoder();

        document.geoCodeRequestCompleteFlag = 0;
        geocoder.geocode({'address' : location}, function(results, status) {    

        if (status === 'OK') {                   
           var latLngArray = [
              +results[0].geometry.location.lat(),
              +results[0].geometry.location.lng()
           ];

           deferred.resolve(mapClass.calculateDistances(clubs, latLngArray));
         } else {
           deferred.reject(status);
         }          
     });             

     return deferred.promise();
}

You would use it like so:

mapClass.setLatLng('123 Some St, Wherever', [/* clubs */])
 .then(function (sortedArray) {
    console.log('Promise resolved with: ', sortedArray);
}, function (err) {
    console.error('Uh oh! An error occurred!', err);
});
Comments