Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > JavaScript: Общие вопросы > Область видимости и локальное хранилище


Автор: s1lver 1.4.2016, 12:12
Доброго времени суток!

Совсем запутался в областях видимости(вроде все проверил) и решил использовать локальное хранилище. Но тут вообще происходит нечто странное.

Что должно произойти, по моему мнению, при каждом проходе цикла:
1) передается название области в геокодер
2) определяются координаты для переданного города
3) записываются(перезаписываются при следующем проходе) в локальное хранилище
4) получаем из локального хранилица координаты
5) помещаем полученные из локального хранилища координы в массив

Код

var geocoder = new google.maps.Geocoder();
var pointData = [];

        for (var i = 0; i < routePoints.length; i++) {
            geocoder.geocode({'address': routePoints[i]}, function(results, status) {
                if (status === google.maps.GeocoderStatus.OK) {
                    localStorage.setItem('invoiceLat', results[0].geometry.location.lat());
                    localStorage.setItem('invoiceLng', results[0].geometry.location.lng());
                }
            });

            var coordinateText = "Долгота: "+localStorage.getItem('invoiceLng')+" Широта: "+localStorage.getItem('invoiceLat');

            pointData.push({"point":routePoints[i], "coordinate":coordinateText});
        }


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

Подскажите, пожалуйста, в чем может быть проблема или более изящное решение?  smile 

Автор: ksnk 1.4.2016, 13:02
Все станет понятно, если обратить внимание, что цикл исполнится сразу весь, сформировав целую кучу запросов,  а ответы на  запросы к гуглу будут приходить уже потом, и дергать функции-обработчики.

Автор: s1lver 1.4.2016, 13:58
Написал такой костыль:

Код

        var pointData = [];
        for (var i = 0; i < routePoints.length; i++) {
            var coordinateJSON;

            $.ajax({
                url: '/geocode',
                type: "POST",
                async:false,
                data: {
                    'address':routePoints[i]
                },
                success: function(data) {
                    coordinateJSON = JSON.parse(data);
                }
            });
            var coordinateText = "Долгота: "+coordinateJSON.lng+" Широта: "+coordinateJSON.lat;

            pointData.push({"point":routePoints[i], "coordinate":coordinateText});
        }


Работает конечно, но как по хорошему сделать не понял  smile 

Автор: ksnk 1.4.2016, 15:27
Что потом делается с pointData?

Примерно так. Во всяком случае - ждать не будет броузер...
Код

var geocoder = new google.maps.Geocoder();
function walkRoutePoint(idx,geo){
   if(idx>=routePoints.length) {
      console.log(geo); // тут делаем что-то полезное с массивом геокодирования.
      return;
   }
   geocoder.geocode({'address': routePoints[i]}, function(results, status) {
          if (status === google.maps.GeocoderStatus.OK) {
              geo.push({idx:idx,lat:results[0].geometry.location.lat(),lng: results[0].geometry.location.lng()});
          }
          walkRoutePoint(idx+1,geo);
    });
}
walkRoutePoint(0,[]);

Автор: s1lver 4.4.2016, 07:36
Цитата

Что потом делается с pointData?


Потом массив помещаю в другой массив(объект), а после из получившегося формирую JSON. 

Код

        var route = {
            route: pointData,
            total_distance: totalDistance
        };

        createInvoice(JSON.stringify(route));


Цитата

Работает конечно, но как по хорошему сделать не понял


На самом деле работает, только если на сервере есть доступ к Интернет. Иначе, скрипт никогда не дождется ответа и вкладка упадет. Так что, мой костыль не подходит в этом случае.

Автор: s1lver 4.4.2016, 08:50
Цитата

Примерно так. Во всяком случае - ждать не будет броузер...


Не взлетело. Все равно данные приходят позже чем формируется массив. Пришлось поправить "костыль" следующим образом:

Код

        var pointData = [];
        for (var i = 0; i < routePoints.length; i++) {
            var coordinateJSON;

            $.ajax({
                url: 'http://maps.googleapis.com/maps/api/geocode/json?address='+encodeURI(routePoints[i])+'&sensor=false',
                type: "POST",
                async:false,
                data: {
                },
                success: function(data) {
                    if (data.status == 'OK') {
                        coordinateJSON = {lng:data.results[0].geometry.location.lng, lat:data.results[0].geometry.location.lat};
                    }
                }
            });

            var coordinateText = "Долгота: "+coordinateJSON.lng+" Широта: "+coordinateJSON.lat;

            pointData.push({"point":routePoints[i], "coordinate":coordinateText});
        }

        var route = {
            route: pointData,
            total_distance: totalDistance
        };

        console.log(JSON.stringify(route));
        createInvoice(JSON.stringify(route));


Как временное решение, думаю, подойдет. :( 

Автор: ksnk 4.4.2016, 18:09
Код

var geocoder = new google.maps.Geocoder();
function walkRoutePoint(idx,geo){
   if(idx>=routePoints.length) {
      console.log(JSON.stringify(route));
      createInvoice(JSON.stringify(route));
      return;
   }
   geocoder.geocode({'address': routePoints[i]}, function(results, status) {
          if (status === google.maps.GeocoderStatus.OK) {
              var coordinateText = "Долгота: "+coordinateJSON.lng+" Широта: "+coordinateJSON.lat;
              geo.push({"point":routePoints[i], "coordinate":coordinateText});
          }
          walkRoutePoint(idx+1,geo);
    });
}
walkRoutePoint(0,[]);

А так?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)