Клуб API Карт

iconContent и balloonContent множество объектов

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

Подскажите плз.

Появилась такая проблема:

Имею объект JSON в котором хранится информация об объктах, которые необходимо вывести на карту. А именно адрес, id из базы и небольшое описание. id должен пойти в iconContent, а описание balloonContent.

for (var i = response.length - 1; i >= 0; i--) {  //Цикл по объекту

var id = response[i].o_id;  //присваиваю id в отдельную переменную

var name = response[i].o_title; //присваиваю описание в отдельную переменную

var myGeocoder = ymaps.geocode(response[i].address); //геокодирую адрес

myGeocoder.then(

   function (res) {

       if (res.geoObjects.getLength()) {

       var point = res.geoObjects.get(0);

         var myPlacemark = new ymaps.Placemark(

       point.geometry.getCoordinates(), {

           iconContent: id, //задаю id в iconContent

                    balloonContent: name //задаю описание в balloonContent

       }, {

           draggable: false,

           hideIconOnBalloonOpen: false

   });

   myMap.geoObjects.add(myPlacemark);  //помещаю метку на карту

       }

    });

}

 


Собсвенно проблема iconContent и balloonContent на карте отображаются одинаковые, как правило это ID и описание последнего элмента в JSON по которому я прохожу, а не соответсвенно адресу, как располагаются в JSON.

p.s.: в JS не силён, но реализовать надо. Если где-то затупил ссори.

 

9 комментариев

 а сам response вы смотрели - там все нормально с сервера выбирается?

Ссылку на вашу страницу не могли бы дать, чтобы посмотреть, почему так выходит?

 

 

Валентин Г.
28 января 2016, 02:42

ссылку к сожалению не могу дать ((

проект на локалке ещё.

 

Что касается response, то сейчас ещё раз вывел console.log до "выше скопированного" цикла. Объект норм, все idы и описнаия разные.

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

а вы в отладчике смотрели - при прохождении цикла, в момент создания метки, id и name имеют нужные значения?

Судя по тому, что цикл по response у вас идет задом наперед, то вписываются как раз самые первые, считанные из response значения или они у вас так и имеют нумерацию от большего к меньшему?

попробую сейчас сымитировать эту ситуацию у себя

 

ага, та же проблема.

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

UPD я так понимаю, что запрос на геокодирование уходит, но поскольоку он асинхронный, скрипт ответа не ждет и крутит цикл дальше. В итоге, когда приходит ответ, цикл успевает прокрутиться до конца и значения id и name  остаются те, что были самыми последними в цикле

почитайте вот тут http://api.yandex.ru/maps/doc/jsapi/2.x/ref/reference/geocode.xml, возможно это наведет вас на какую-то правильную мысль. у меня пока ничего путного в голове не оформилось :)

 

 

 

 

 

 

 

 

это самая распространненная (детская) ошибка начинающих javascript-разработчиков. прочитайте про замыкания и вообще про область видимости, тогда все сразу встанет на свои места

Валентин Г.
28 января 2016, 02:42

Да спасибо. Уже прочёл.

В своём посте я написал, что в JS не спец

Андрей Грэй
28 января 2016, 02:42

.then() - асинхронная функция, т.е. выполняется скорее всего тогда, когда весь ваш цикл for уже пробежался.

да и geocode, по-моему.

 

Вам нужно немного поменять порядок действий.

 

Лучше будет, если вы на php (или том языке что вы используете), напишите функцию, которая будет использовать геокодирование до (http://api.yandex.ru/maps/doc/geocoder/) того, как будет формироваться страница. И уже в цикле просто создавать перем точки на карте останется. Кстати, в этом случае лучше результаты геокодирования сразу в БД залить, чтобы не заниматься запросом к геокодеру при всяком открытии страницы, а делать это только для новых точек на карте.

small_butterfly_long_long_as_long_as_i_can_do_it_here
28 января 2016, 02:42

Вот так будет работать

response.forEach(function(item) {

     var id = item.o_id; //присваиваю id в отдельную переменную

     var name = item.o_title; //присваиваю описание в отдельную переменную

    var myGeocoder = ymaps.geocode(item.address); //геокодирую адрес

    myGeocoder.then(function (res) {

             if (res.geoObjects.getLength()) {

                  var point = res.geoObjects.get(0);

                  var myPlacemark = new ymaps.Placemark(

                           point.geometry.getCoordinates(), {

                           iconContent: id, //задаю id в iconContent

                           balloonContent: name //задаю описание в balloonContent

                  }, {

                          draggable: false,

                          hideIconOnBalloonOpen: false

                 });

                 myMap.geoObjects.add(myPlacemark); //помещаю метку на карту

         }

  });

});

 

рекомендую почитать про замыкания в javascript - узнаете много интересного

Валентин Г.
28 января 2016, 02:42

Спасибо, большое проблема решена. Сделал геокодирование на стороне сервака.

 

Спасибо всем большое!