Итерация через массив при выполнении запроса для каждой записи
Вот моя проблема. У меня есть массив, содержащий название городов, которые мне нужны для поиска погоды. Поэтому я просматриваю каждый город и выполняю запрос 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 ]); },