遍历数组并为每个条目执行请求

4

我遇到了一个问题。我有一个包含城市名称的数组,我需要查找每个城市的天气。所以我正在循环遍历每个城市,并执行 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' );
                }
            }
        });
    }
});

我遇到的问题是,在成功函数中无法访问城市名称(通过cities [cityIdx])。我在for循环和成功函数中插入了alert()并且似乎循环执行 cities.length 次,然后我得到了成功函数的警报。我的目标只是循环遍历每个城市,获取天气信息,并将其显示在我的页面上以及相关的城市名称。
此外,您建议我应该如何分离内容和演示?
谢谢。 :)
5个回答

5

我猜想你的问题与http://ejohn.org/apps/learn/上的例子类似。在处理for循环时,闭包中创建的变量cityIdx会被更新,因此当你的成功函数运行时,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)
//...

5

由于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
    }
});

我认为你应该删除“new”。 - Javier
尝试删除 "new" 会导致语法错误。我认为这是因为您正在创建一个函数实例以供立即使用,而不是将其传递给 .ready() 函数。我认为 .ready() 函数将传递的函数对象放入队列中以便稍后实例化和执行。 - patridge

3
为什么不使用jQuery来遍历你的数组呢?使用jQuery的each函数:
    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' ); 
                    }
                }
        });
    });
});

成功函数中的警报显示了正确的城市。

谢谢。我已经更新了我的函数,使用了for each。 :) - Mike

1

最简单的方法是让您的AJAX请求返回城市的名称。


1

出于各种原因,我会尝试将成功函数提取到一个单独定义的函数中,然后在包括城市名称的ajax调用中创建一个闭包。所以首先,需要一个单独的成功处理程序:

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

然后修改 ajax 调用中的成功绑定:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接