Добавление обещания к вызову API Карт Google

Мне нужно вернуть массив из функции в Javascript/jQuery, но функция возвращается до того, как массив был установлен (так как это вызов AJAX).

Мне было рекомендовано использовать обещание, но я не использовал их раньше и до сих пор не смог реализовать это в своем коде. Вот мой код:

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;
            }           
        });             
    }

Как вы можете видеть, переменная sortedArray пуста, когда я возвращаюсь. Есть ли у кого-нибудь какие-либо идеи относительно того, как я могу добавить в него блокирующий код, чтобы гарантировать, что переменные массива установлены перед возвратом? благодаря

Ответ 1

То, как вы используете обещания, заключается в том, что вы создаете обещание, а затем возвращаете это обещание из своего метода. Это обещание имеет такие методы, как .then(successHandler, errorHandler) которые позволяют вам указывать функции для выполнения, когда обещание разрешено (задано значение). Затем вы разрешаете обещание, когда вы в какой-то момент в будущем возвращаете результаты вызова геокодера.

В jQuery обещания называются Отсрочками.

Тогда ваш код изменится на следующее:

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();
}

Вы бы использовали его так:

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);
});

Ответ 2

Если вы используете официальный официальный модуль NPM Google Maps, вы можете сделать это намного проще и чище.

Во-первых, вам нужно инициализировать клиент с помощью свойства Promise:

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

Затем все, что вам нужно сделать, это использовать asPromised() после чего вам будет полезно:

googleMapsClient.geocode({
  address: '1600 Amphitheatre Parkway, Mountain View, CA'
})
.asPromise()
.then(response =>  response.json.results)
.catch(err => console.log(err))