Итерация через массив при выполнении запроса для каждой записи

Вот моя проблема. У меня есть массив, содержащий название городов, которые мне нужны для поиска погоды. Поэтому я просматриваю каждый город и выполняю запрос AJAX для получения погоды.

var LOCATION = 'http://www.google.com/ig/api?weather=';

$( document ).ready( function() {
    for( var cityIdx = 0; cityIdx < cities.length; cityIdx++ ) {
        $.ajax({
            type: 'GET',
            url: LOCATION + cities[ cityIdx ],
            dataType: 'xml',
            success: function( xml ) {
                if( $( xml ).find( 'problem_cause' ) != 0 ) {
                    // Do what I want with the data returned
                    var weather = $( xml ).find( 'temp_c' ).attr( 'data' );
                }
            }
        });
    }
});

Проблема, с которой я сталкиваюсь, заключается в том, что в функции успеха я не могу получить доступ к имени города (через города [cityIdx]). Я вставил alert() в цикл for и функцию успеха, и кажется, что цикл запускается city.length раз, затем я получаю предупреждения о функции успеха. Моя цель - просто прорезать каждый город, получая погоду и показывая его на моей странице вместе с названием города.

Кроме того, что вы предлагаете мне сделать, чтобы разделить контент с презентацией?

Спасибо.:)

Ответ 1

Я подозреваю, что ваша проблема похожа на пример в http://ejohn.org/apps/learn/. Индексная переменная cityIdx обновляется в закрытии, которое вы создаете при обработке цикла for, поэтому к моменту запуска вашей функции при успешном выполнении cityIdx укажет на последний элемент в массиве. Решение заключается в использовании анонимной функции для создания независимого контекста, где значение индекса не обновляется.

//...
success: (function(cities, idx) {
    return function( xml ) {
      if( $( xml ).find( 'problem_cause' ) != 0 ) {
        // Do what I want with the data returned
        // use cities[idx]
        var weather = $( xml ).find( 'temp_c' ).attr( 'data' );
      }
    };
  })(cities, cityIdx)
//...

Ответ 2

Так как Javascript использует функции для закрытия, я нашел самый простой способ для меня просто обернуть содержимое цикла for встроенной функцией, которая копирует текущее название города в переменную, к которой всегда будет иметь доступ.

$(document).ready(function() {
    for (var cityIdx = 0; cityIdx < cities.length; cityIdx++) {
        new function() {
            var currentCity = cities[cityIdx];
            $.ajax({
                type: 'GET',
                url: LOCATION + currentCity,
                dataType: 'xml',
                success: function(xml) {
                    alert(currentCity);
                    if ($(xml).find('problem_cause') != 0) {
                        // Do what I want with the data returned
                        var weather = $(xml).find('temp_c').attr('data');
                    }
                }
            });
        }(); // the "();" calls the function we just created inline
    }
});

Ответ 3

Почему бы не использовать jQuery для итерации по вашему массиву? Используйте каждую функцию jQuery:

    var LOCATION = 'http://www.google.com/ig/api?weather=';

$( document ).ready( function() {

    $.each(cities, function()  {
    //assign the current city name to a variable
        var city = this;
        $.ajax({
                type: 'GET',
                url: LOCATION + city,
                dataType: 'xml',
                success: function( xml ) {
                    if( $( xml ).find( 'problem_cause' ) != 0 ) {
                        alert(city);
                            // Do what I want with the data returned
                        var weather = $( xml ).find( 'temp_c' ).attr( 'data' ); 
                    }
                }
        });
    });
});

Предупреждение в функции успеха отображает правильный город.

Ответ 4

Самый простой способ сделать запрос AJAX вернуть название города.

Ответ 5

По целому ряду причин я бы попытался вытащить функцию успеха в отдельно определенную функцию, а затем создать закрытие для нее в вызове ajax, который включает название города. Итак, сначала, отдельный обработчик успеха:

function city_success(xml, name) {
  // your success handling code here
}

И затем измените привязку успеха в вызове ajax:

success: function (xml) { city_success(xml, cities[ cityIdx ]); },