Проблема с AJAX в a для l oop: Как я могу сделать ajax вызов для каждого элемента массива? - PullRequest
2 голосов
/ 27 февраля 2020

Я новичок в StackOverflow :)

Мне нужна помощь: я пытаюсь создать обратный геокод (получить адрес из координат). У меня есть хороший URL, который работает с ajax. У меня много координат для преобразования в адрес, поэтому я сначала пытаюсь использовать массив с 4 координатами в JSfiddle.

Что я хочу получить, так это то, что мой скрипт добавляет все адреса в мой массив. Я пытаюсь использовать для l oop и для каждого элемента массива вызов ajax, который находит хорошие координаты.

Вы можете найти вызов по этой ссылке (я поставил скрипт после ссылки): https://jsfiddle.net/e2wr3umy/

мой код, который работает для элемента:

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
$.ajax({

                     url: 'https://reverse.geocoder.ls.hereapi.com/6.2/reversegeocode.json',
                      type: 'GET',
                      dataType: 'jsonp',
                      jsonp: 'jsoncallback',
                      data: {
                        prox: '43.564624, 3.847154,250',
                        mode: 'retrieveAddresses',
                        maxresults: '1',
                        gen: '9',
                        apiKey: 'NOT_THE_REAL_API_KEY'
                      },
                      success: function (data) {
                        var re = JSON.stringify(data);
                        console.log(data);
                        var num = (data.Response.View[0].Result[0].Location.Address.HouseNumber);
                        var rue = (data.Response.View[0].Result[0].Location.Address.Street);
                        var ville = (data.Response.View[0].Result[0].Location.Address.City);
                        var CP = (data.Response.View[0].Result[0].Location.Address.PostalCode);
                        console.log(num, rue, CP, ville)
                      }
                    });

Затем я пытаюсь использовать массив из 4 элементов, это ссылка: https://jsfiddle.net/L07pjwba/

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>

var adresse = [['43.564624, 3.847154',1],['43.564624, 3.447154',27],['43.64624, 3.727154',75],['43.564624, 3.617154',254]];


for (i =0; i<adresse.length; i++) {
console.log("element", adresse[i]);
$.ajax({
                      url: 'https://reverse.geocoder.ls.hereapi.com/6.2/reversegeocode.json',
                      type: 'GET',
                      dataType: 'jsonp',
                      jsonp: 'jsoncallback',
                      data: {
                        prox: adresse[i][0].concat(', 250'),
                        mode: 'retrieveAddresses',
                        maxresults: '1',
                        gen: '9',
                        apiKey: 'NOT_THE_REAL_API_KEY'
                      },
                      success: function (data) {
                        var re = JSON.stringify(data);
                        console.log("data", data);
                        var num = (data.Response.View[0].Result[0].Location.Address.HouseNumber);
                        var rue = (data.Response.View[0].Result[0].Location.Address.Street);
                        var ville = (data.Response.View[0].Result[0].Location.Address.City);
                        var CP = (data.Response.View[0].Result[0].Location.Address.PostalCode);
                        adresse[i].push(num, rue, ville, CP);

                      }
                    });

}
console.log("adresse : ",adresse);

Но результат не тот, который я ожидаю : похоже, что вызов ajax начинается после окончания for для l oop, даже если он внутри for al oop. Я попробовал с async: false в ajax, но это ничего не изменило.

1 Ответ

4 голосов
/ 27 февраля 2020

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

По сути, ваш код сообщает службе геокодирования, чтобы вы знали об адресах. Затем вы печатаете массив. Когда-нибудь в будущем служба геокодирования ответит вам, но массив уже распечатан, и у JavaScript нет машины времени.

Принцип bas c заключается в том, что вы никогда не сможете использовать значение, которое вы получаете от функции asyn c где угодно, за исключением обратного вызова этой функции (или ее цепочки обещаний) и функций, которые вызываются оттуда. В своем первом фрагменте вы делаете это правильно: вы используете console.log внутри обратного вызова. Во втором фрагменте вы перемещаете его за пределы обратного вызова, и это является источником ваших проблем.

Вот как правильно написать это. $.ajax возвращает «обещание», которое можно связать с помощью .then, чтобы указать, что что-то должно быть сделано, когда обещание выполнено (т.е. вы получаете ответ от службы геокодирования). Вы можете использовать Promise.all, чтобы дождаться выполнения всех обещаний в массиве. Все вместе, это должно выглядеть так (я изменил минимальный объем вашего кода, я бы написал его немного по-другому):

var adresse = [
  ['43.564624, 3.847154', 1],
  ['43.564624, 3.447154', 27],
  ['43.64624, 3.727154', 75],
  ['43.564624, 3.617154', 254]
];

var promises = [];
for (i = 0; i < adresse.length; i++) {
  console.log("element", adresse[i]);
  var promise = $.ajax({
    url: 'https://reverse.geocoder.ls.hereapi.com/6.2/reversegeocode.json',
    type: 'GET',
    dataType: 'jsonp',
    jsonp: 'jsoncallback',
    data: {
      prox: adresse[i][0].concat(', 250'),
      mode: 'retrieveAddresses',
      maxresults: '1',
      gen: '9',
      apiKey: 'NOT_THE_REAL_API_KEY'
    },
  }).then(function(data) {
    var num = (data.Response.View[0].Result[0].Location.Address.HouseNumber);
    var rue = (data.Response.View[0].Result[0].Location.Address.Street);
    var ville = (data.Response.View[0].Result[0].Location.Address.City);
    var CP = (data.Response.View[0].Result[0].Location.Address.PostalCode);
    adresse[i].push(num, rue, ville, CP);
  });
  promises.push(promise);
}

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