Google геокодирует несколько адресов в цикле с помощью JavaScript, как мне узнать, когда все будет сделано? - PullRequest
13 голосов
/ 29 января 2012

У меня есть форма, которая запрашивает список мест (не много, обычно только 3 или 4, но это число является динамическим). Когда форма отправлена, мне нужно проанализировать данные, использовать геокодирование Google для определения местоположения, а затем нарисовать линию, соединяющую точки по порядку. У меня работает синтаксический анализ, но я застрял в части геокодирования, в основном из-за асинхронного характера этого. Предположим, мои адресные строки хранятся в массиве «адреса», вот как далеко я получил:

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.
}

Рисовать линию достаточно просто, я делал это раньше, когда пользователи указывали географические координаты широты и долготы. Моя проблема в том, что, поскольку координаты добавляются только в обратном вызове, как я узнаю, когда это будет сделано? Я не могу просто выбросить это в функцию и вставить обратный вызов, потому что мне нужно подождать, пока все координаты не будут обработаны.

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

NB. Я бомбил этот код вручную, поэтому возможны опечатки Мой реальный код до сих пор «работает», я просто не знаю, от кого перейти, что я должен делать, когда все адреса обработаны. Кроме того, это в настоящее время разрабатывается как внутреннее приложение для тестирования. Как только тестирование будет завершено, оно будет полностью соответствовать Условиям использования Google. Это означает, что у меня нет страницы, на которую я могу сослаться. Все приложение также содержит более 2000 строк кода и на данный момент содержит некоторую частную информацию о компании, которая, в конечном итоге, будет постепенно исключена, поэтому вставка всего объекта или его рассылка невозможны. Я надеюсь, что это не слишком большая проблема.

Ответы [ 4 ]

13 голосов
/ 29 января 2012
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
});

Использование функции обратного вызова удивительно

8 голосов
/ 29 января 2012

Вы можете проверить, все ли вызовы завершены, сравнив количество результатов с количеством адресов:

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
    ...
}
2 голосов
/ 14 сентября 2015

Если вы используете такие библиотеки, как jQuery, вы можете воспользоваться Deferred Object для выполнения цепочек запросов с помощью функции geocoder.geocode.

Пример

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"/>
0 голосов
/ 03 января 2016

Это довольно старый, но есть проблема закрытия в данных ответах , поэтому конечный результат имеет одинаковый лат, длинный для всех адресов .

Лучше перебирать все адреса, используя address.forEach , чтобы каждый геокодированный адрес содержался, и это должно работать нормально, если целевые браузеры современны. В противном случае вам нужно определить внешнюю функцию для решения проблемы печально известного цикла javascript . Вот решение forEach для массива адресов:

            var getLatLng = function(addresses, callback) {
            var coords = [];

            addresses.forEach(function(address) {

                var geocoder = new google.maps.Geocoder();
                geocoder.geocode({'address': address}, function (results, status) {

                    if (status == google.maps.GeocoderStatus.OK) {
                        var lat = results[0].geometry.location.lat();
                        var lng = results[0].geometry.location.lng();
                        coords.push([lat, lng]);

                        // all addresses have been processed
                        if (coords.length === addresses.length)
                            callback(coords);
                    }
                });
            });
        }

        getLatLng(allAddresses, function (results) {
            console.log("received all addresses:", results);
        });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...