多个AJAX调用以随机顺序返回JSON对象

时间:2015-02-15 17:13:49

标签: jquery ajax

我正在尝试存储像这样返回的JSON对象

<div id="tabs-1" class="LIVE"></div>
<div id="tabs-2" class="past-matches"></div>
<div id="tabs-3" class="upcoming-matches"></div>    

使用以下脚本。

$(function() {
query=["select * from cricket.scorecard.live.summary","select * from      cricket.past_matches", "select * from cricket.upcoming_matches"]
container=[".LIVE",".past-matches",".upcoming-matches"]
container_no=0
query_no=0;
for( var section=0;section<query.length;section++)
{   
      $.ajax({
        url: "https://query.yahooapis.com/v1/public/yql",        
        jsonp: "callback",         
        dataType: "jsonp",        
        data: {
            q: query[query_no++],
            env:"store://0TxIGQMQbObzvU4Apia0V0",           
            format: "json"
        },       
        // Work with the response
        success: function(data ) {
             console.log( data ); // The problem: returns JSON objects in different order everytime the page reloads

             //I would like to store data like this
             if(container_no>0)
             {  
                if(container_no==1)
                {   $(container[container_no]).append('<p>recent match data</p>');
                    container_no++; 
                }
                else
                {
                    $(container[container_no]).append('<p>upcoming match data</p>');
                     container_no++; 
                }                   
            }   
            else{
               $(container[container_no]).append('<p>live match data</p>');
               container_no++;
            }
        }
    });
   }    
 });

问题是每次重新加载页面时JSON对象都以不同的顺序返回,所以我无法将数据保存在正确的div中。我想我做了一个涉及变量范围的错误。 这是小提琴:FIDDLE

1 个答案:

答案 0 :(得分:2)

Ajax调用是异步的(&#34; A&#34;代表Ajax)。因此,它们具有不确定的执行时间,并且当您执行多个Ajax调用时,没有保证结果将到达的顺序。

因此,如果你想知道哪个结果是哪个(例如哪个是第一个,第二个等等),你必须创建一个对每个ajax调用都是唯一的计数器。一种方法是将每个Ajax调用放入函数调用并将计数器传递给该函数调用。此函数将创建一个闭包,当结果返回时,将为您维护计数器。

这是一个使用函数的版本,该函数来自使用.forEach()来迭代查询数组。我还做了一些其他修改来简化代码:

$(function() {
    var query = ["select * from cricket.scorecard.live.summary", "select * from      cricket.past_matches", "select * from cricket.upcoming_matches"];
    var container = [".LIVE", ".past-matches", ".upcoming-matches"];
    var msg = ['<p>live match data</p>', '<p>recent match data</p>', '<p>upcoming match data</p>'];
    query.forEach(function(queryVal, cnt) {
        $.ajax({
            url: "https://query.yahooapis.com/v1/public/yql",
            jsonp: "callback",
            dataType: "jsonp",
            data: {
                q: queryVal,
                env: "store://0TxIGQMQbObzvU4Apia0V0",
                format: "json"
            },
            // Work with the response
            success: function(data) {
                console.log(data);
                $(container[cnt]).append(msg[cnt]);
            }
        });
    }
});

这是另一个创建IIFE(立即调用的函数表达式)来解决同样问题的版本:

$(function() {
    var query = ["select * from cricket.scorecard.live.summary", "select * from      cricket.past_matches", "select * from cricket.upcoming_matches"];
    var container = [".LIVE", ".past-matches", ".upcoming-matches"];
    for (var section = 0; section < query.length; section++) {
        // add IIFE so we can capture the section number uniquely for each ajax call
        (function(cnt) {
            $.ajax({
                url: "https://query.yahooapis.com/v1/public/yql",
                jsonp: "callback",
                dataType: "jsonp",
                data: {
                    q: query[cnt],
                    env: "store://0TxIGQMQbObzvU4Apia0V0",
                    format: "json"
                },
                // Work with the response
                success: function(data) {
                    console.log(data);

                    var msg;
                    if (cnt === 0) {
                        msg = '<p>live match data</p>'
                    } else if (cnt === 1) {
                        msg = '<p>recent match data</p>';
                    } else {
                        msg = '<p>upcoming match data</p>';
                    }
                    $(container[cnt]).append(msg);
                }
            });
        })(section);
    }
});

注意,我还在所有局部变量中添加了var,因此您不会意外地创建全局变量。


如果你真的想等到收集到所有结果,那么你可以完全按照循环顺序添加它们,那么你可以使用jQuery&#39; $.when()来做到这一点。

$(function() {
    var query = ["select * from cricket.scorecard.live.summary", "select * from      cricket.past_matches", "select * from cricket.upcoming_matches"];
    var container = [".LIVE", ".past-matches", ".upcoming-matches"];
    var msg = ['<p>live match data</p>', '<p>recent match data</p>', '<p>upcoming match data</p>'];
    var promises = [];
    query.forEach(function(queryVal, cnt) {
        promises.push($.ajax({
            url: "https://query.yahooapis.com/v1/public/yql",
            jsonp: "callback",
            dataType: "jsonp",
            data: {
                q: queryVal,
                env: "store://0TxIGQMQbObzvU4Apia0V0",
                format: "json"
            },
        }));
    }
    // wait for all ajax results to be done
    $.when.apply($, promises).then(function() {
        for (var i = 0; i < arguments.length; i++) {
            // iterate all results in order
            console.log(arguments[i][0]);
        }
    });
});