Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 788
James Avatar asked Sep 29 '14 08:09

James


2 Answers

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);
});
like image 143
GregL Avatar answered Sep 21 '22 04:09

GregL


If you are using the official Google Maps Official NPM module, You can do it much easier and cleaner.

First, you need to initialize the client with a Promise property:

const googleMapsClient = require('@google/maps').createClient({
  key: 'your API key here',
  Promise: Promise
});

Then, all you need to do is to use asPromised() and after that you are good to go:

googleMapsClient.geocode({
  address: '1600 Amphitheatre Parkway, Mountain View, CA'
})
.asPromise()
.then(response =>  response.json.results)
.catch(err => console.log(err))
like image 28
ambodi Avatar answered Sep 22 '22 04:09

ambodi