0

我正在编写一个简单的天气应用程序并且被 for 循环卡住了。这个想法是获取一小部分位置的天气,并将每个位置的预测加载到自己的 div 中。这是到目前为止的代码:

$(function () {
    var z = ["location ID1", "location ID2", etc.];
    var n = ["location name1", "location name2", etc];
    for (j = 0; j<z.length; j++) {
        weatherQuery = 'SELECT * FROM rss WHERE url="http://xml.weather.yahoo.com/forecastrss/' + z[j] + '_c.xml"';
        $('#weatherData').append($('<div/>', {id: 'c' + j}));
        $('#c' + j + '').append('' + n[j] + '');
        var weatherUrl = 'http://query.yahooapis.com/v1/public/yql?q=' + encodeURIComponent(weatherQuery) + '&format=json';
        $.getJSON(weatherUrl + '&callback=?', function (data) {
            var weatherForecasts = data.query.results.item.forecast;
            for (i=0; i<weatherForecasts.length; i++) {
                var code = weatherForecasts[i].code;
                $('#c' + j + '').append('<table style = border:none><tr><td class = weather-date>' + weatherForecasts[i].day + '</td><td class = weather-icon style = background-position:-' + (61 * code ) + 'px 0px></td><td class = weather-min>' + weatherForecasts[i].low + '°</td><td class = weather-max>' + weatherForecasts[i].high + '°</td></tr></table>');              
            } 
        });
    }
});

据我从 Firebug 得知,第一部分有效 - 正在检索正确的天气数据,并且正在父 div 中创建新的 div。正确的位置名称也被附加到每个新的 div 中。如果它倒下,则将天气数据附加到每个 div。在第二个(最后一个)附加语句中识别子 div 的正确方法是什么,以便每个 div 有一次天气数据解析循环的迭代?谢谢。

4

1 回答 1

1
for (j = 0; j<z.length; j++) {
    $.getJSON(..., function (data) {
        $('#c' + j + '').append(...

循环执行z.length次数,启动z.lengthAJAX请求,完成j等于z.length终止循环。

然后,很久以后(因为 AJAX 中的“A”表示“异步”)请求完成并调用每个回调函数。他们j用来选择将结果附加到哪个 div。但j仍然z.length是循环结束时的样子。在变量上创建一个带有闭包的函数并不意味着从创建函数的那一刻起就记住了变量的值。每个函数都有相同的引用j

(实际上你根本没有闭包,因为你的循环变量ji没有声明var,所以它们是偶然的全局变量。)

您可以在创建函数时记住局部变量的值,方法是将其包装在一个单独的函数中,该变量在(或function.bind在 ECMAScript 5 中使用)。一种简单的方法是使用基于回调函数的循环而不是for

var places = [
    {id: 'location1', name: 'Location One'},
    ...
];

$.each(places, function(place_i, place) {
    var yql = 'SELECT * FROM rss WHERE url="http://xml.weather.yahoo.com/forecastrss/' + encodeURIComponent(place.id) + '_c.xml"';
    var div = $('<div/>').attr('id', 'c'+place_i)).text(place.name);
    $('#weatherData').append(div);

    $.ajax({
        url: 'http://query.yahooapis.com/v1/public/yql',
        data: {q: yql, format: 'json'},
        dataType: 'jsonp'
    ).done(function(json) {
        var forecasts = data.query.results.item.forecast;
        var table = $('<table style="border: none">'); // prefer class/stylesheet
        $.each(forecasts, function(forecast_i, forecast) {
            table.append($('<tr>').append(
                $('<td class="weather-date">').text(forecast.day)
            ).append(
                $('<td class="weather-icon">').css('background-position', forecast.code*-61 + 'px 0')
            ).append(
                $('<td class="weather-min">').text(forecast.low+'°')
            ).append(
                $('<td class="weather-max">').text(forecast.high+'°')
            ));
        });
        div.html(table);
    });
});

笔记:

  • 使用 jQuery 自动转换数据参数,避免encodeURIComponent在 JSON URL 上手动调用。

  • 避免将字符串变量中的 HTML 内容粘在一起。对于 HTML 特殊字符,它会失败,并且可能会引入安全问题 (XSS)。要设置文本内容,请使用 jQuery text()

  • id如果您在这样的 JS 变量中保留对元素的引用,您可能根本不需要给元素一个引用。

于 2013-10-03T23:38:44.060 回答