Клуб API Карт

Работа с результатами геокодирования

Пост в архиве.

Предположим в массиве есть несколько географических объектов. Часть из них задана координатами, а часть адресами. Задача: вывести их на карту.

Я начинаю перебирать объекты и если объект задан координатами, то делаю из него GeoPoint и обрабатываю (создаю PlaceMark и добавляю в массив для дальнейшего расчета масштаба).

Если же объект задан адресом, я передаю адрес в функцию на геокодирование, чтобы получить GeoPoint, создать PlaceMark и т.д. Проблема в том, что я не знаю, когда их получу, а программа в это время идет дальше.

Так вот как мне дождаться результатов геокодирования? Или как решить задачу другим способом?

4 комментария
Если это массив, то наверное у массива есть размер. Вот и ставьте цикл/условие, используя размерность массива.
Александр Новиков
28 января 2016, 08:09
У геокодера есть callback функция - в этой функции и ставьте маркер по результату геокодирования. Дополнительно можно еще где-то отмечать что для данной точки координаты найдены. Если на пальцах, то когда вы запускаете геокодирование для адреса, то у вас есть возможность задать функцию, которая выполняется после того как были получены результаты. Что именно будет делать данная функция зависит от вашей задачи и от вашего воображения :)
Я бы посоветовал один раз геокодировать все адреса и закэшировать их. Далее работать только с координатами. Это удобнее.

Ниже я продемонстрирую как можно отловить момент, когда все результаты геокодирования получены.

Для этого введем переменную geocodeCallCount, обозначающей количество объектов, для которых необходимо запустить процесс геокодирования.

При запуске геокодирования будем увеличивать эту переменную, при окончании геокодирования - уменьшать. Таким образом geocodeCallCount - это своего рода семафор.

Функция isFinish проверяет завершенность всех процессов геокодирования по переменной geocodeCallCount. Если она равна нулю, то это означает, что обработка объектов завершена и можно производить какие-либо действия (например, добавление объектов на карту).

Вот код:
    // Координаты или адреса географических объектов
var data = ["37.609218,55.753559", "40.411836,56.139587", "Питер", "Ярославль", "43.867484,56.293042"],

    // Группа для будущих объектов
    objects = new YMaps.GeoObjectCollection(),
   
    // Количество вызовов геокодера
    geocodeCallCount = 0;

// Обработка данных
for (var i = 0, placemark, l = data.length; i < l; i++) {

    // Если задана координаты, то сразу преобразуем в геоточку
    if (/\d{1,}(?:\d{1,})?\,\d{1,}(?:\d{1,})?/.test(data[i])) {
        objects.add(new YMaps.Placemark(YMaps.GeoPoint.fromString(data[i])));
    } else { // Если требуется геокодирование, то
   
        // Счетчик вызовов геокодирования увеличиваем
        geocodeCallCount++;
       
        // Геокодируем
        var geocoder = new YMaps.Geocoder(data[i]);
       
        // Слушаем события завершения геокодирования
        YMaps.Events.observe(geocoder, [geocoder.Events.Load, geocoder.Events.Fault], function (geocoder) {
            // Если были найдены результаты
            if (geocoder.length()) {
                // Первый результат добавляем на карту
                objects.add(geocoder.get(0));
            }
           
            // Финиш?
            geocodeCallCount--
            isFinish();
        });
    }
}

// Финиш?
isFinish ();

// Функция для проверки окончания процесса геокодирования
function isFinish () {
    // Если все объекты сгеокодированы, то добавляем объекты на карту
    if (!geocodeCallCount) {
        map.addOverlay(objects);
    }
}


Благодарю, реализовал схожим образом, но куда более коряво.