7

我正在尝试循环调用 3 个具有相同命名约定和结构(但数据略有不同)的不同 json 文件的 ajax 调用。自从我在论坛中阅读 Alnitak 的回复(jQuery ajax 成功回调函数定义)以来,我一直在使用延迟对象而不是成功选项,以便我的 ajax 处理和回调处理可以解耦。下面是我的代码:

<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=ISO-8859-1" />

<title>Stuff</title>
<script src="jquery-1.9.1.min.js" type="text/javascript"></script> 
</head>

<body>
<script Language="JavaScript">

    var myData = [];
    var myURL =  ["ticker1.json","ticker2.json","ticker3.json"];    //New Array for my URLs

    function getData(m) {

        return $.ajax({
            url : myURL[m],  //<<<---Want to loop through this array
            type : 'GET',
            dataType: 'json'
        });

    }

    function handleData(data){

        for (var i=0; i<data.test.msgOne.length; i++){
            myData[i] = data.test.msgOne[i];
        }

    };



    for (var j=0; j<3; j++){

        console.log(j);  //<<---First console statement
        var ajaxCall = getData(j).done(handleData);

        $.when(ajaxCall).done(function(){ //wait until the ajax call is done before writing

            console.log(j);  //<<---Second console statement

            for (var k=0; k<3; k++){
                document.write(myData[k])
                document.write('<br><br>');
            }

        });

    }

</script>
</body>
</html>

我的代码由一个名为 getData 的函数组成,它执行 ajax 调用,然后是一个名为 handleData 的函数,它简单地遍历来自 ajax 调用的 json 文件中的数据,并将数据存储在数组 myData 中。然后 for 循环尝试将数组 myData 的数据输出到屏幕。但是,问题是我只从屏幕上的第一个 json 文件输出中获取数据,而不是按顺序获取所有三个。

所以我所做的是在 for 循环中输入两个 console.log 语句:一个在 ajax 调用之前,一个在 ajax 调用完成之后。第一个console.log按预期顺序输出0,1,2,第二个给出3,这是出乎意料的。因此,我假设在计数器完成之前没有返回 ajax 调用。我用一些逻辑语句和一个while循环替换了for循环(是的,我知道代码无限期运行的危险),如下所示:

    var j=0;
    var whileFlag= new Boolean(1);
    var ajaxFlag = new Boolean(1);

    while (whileFlag) {

        if (ajaxFlag > 0) {
            ajaxFlag = 0;
            console.log(j);
            var ajaxCall = getData(j).done(handleData);
        }
        $.when(ajaxCall).done(function(){
            console.log(j);
            for (var k=0; k<3; k++){
                document.write(myData[k])
                document.write('<br><br>');
            }
            ajaxFlag = 1;
            j++;
        });

        if (j>=3) {whileFlag = 0};
    }

替换代码试图强制 ajax 调用完成,然后在进入下一个 ajax 调用之前执行代码。好吧,最终的结果是一个冻结的浏览器,这不是 bueno。有谁知道我如何能够将我的每个 json 文件的 myData 数组写入屏幕?任何帮助和建设性意见表示赞赏。另外,我需要保持 ajax 调用异步,因为我将来会使用 jsonp 数据类型。

附加问题:我认为浏览器挂起是由于ajax没有返回调用,但问题是为什么?如果我在第一个示例中选择不实现 for 循环,而只是将 j 变量显式设置为 0、1 或 2,则所选 json 文件的数据打印输出良好,但如果我做的不止它只会打印第一个 json 文件中的数据集。就好像不可能进行多个 ajax 调用之类的。任何见解和帮助表示赞赏。谢谢。

4

3 回答 3

2

问题是你的while循环相当于......

 while (whileFlag) {

    if (ajaxFlag > 0) {
        ajaxFlag = 0;
        console.log(j);
        var ajaxCall = getData(j).done(handleData);
    }
    // Some thrid party (asynch Handler) changes j
    if (j>=3) {whileFlag = 0};
}

所以理想情况下,直到 Ajax 完成你的代码运行为

 while (whileFlag) {
  if (j>=3) {whileFlag = 0};
    }

这会挂起您的浏览器...

如果您真的想等待第二次 Ajax 调用直到第一次完成,依此类推..

 function getData(m) {

    return $.ajax({
        url : myURL[m],  //<<<---Want to loop through this array
        type : 'GET',
        dataType: 'json',
        myJ: m
    });

    }


 function handleData(data){

    for (var i=0; i<data.test.msgOne.length; i++){
        myData[i] = data.test.msgOne[i];
    }

    for (var k=0; k<3; k++){
            document.write(myData[k])
            document.write('<br><br>');
    }
    if(this.myJ<2){
    var myJ=this.myJ;
       setTimeout(function(){
           getData((myJ+1)).done(handleData).fail(failed);
           }, 100);
    }
};



 getData(0).done(handleData);

function failed(jqXHR, textStatus, errorThrown){
 alert("textStatus="+textStatus);
alert("Error= "+errorThrown);
}

根据带有警报的评论,如果它工作,然后使用 settimeout .. 它会工作

于 2013-05-16T17:17:08.053 回答
0

如果你知道总是有三个电话,你可以这样做:

function getData(url) {
    return $.ajax({
        url: url,
        //...
    });
}

function handleData(data1, data2, data3) {
    //display the data however you like
}

$(document).ready(function() { 

    var request1 = getData(myUrl[0]);
    var request2 = getData(myUrl[1]);
    var request3 = getData(myUrl[2]);

    $.when(request1, request2, request3)
        .done(function(result1, result2, result3) {
            alert(result1.test.msgOne[0]);
        });    

});

在这种情况下,handleData()只会在三个调用都完成后调用一次。

如果您不知道将有多少结果,您可以遍历 myUrl 数组并将deferreds 推入数组。尝试此链接deferred以获取将对象数组传递给$.when().

另一个编辑

我已经更新了原始代码。我认为您正在挂断延迟对象。延迟对象(request1例如 )不包含响应。当您调用$.when(request1).done(function(result1) { });request1 的 json 结果时,会将其传递给函数。

于 2013-05-17T14:51:23.823 回答
0

以下是三个 json 文件,以防您想自己测试:

  • ticker1.json:

    {“测试”:{“msgOne”:[“ticker1远程一”,“ticker1远程二”,“ticker1远程三”],“msgTwo”:“Remote2”,“msgThree”:“Remote3”}}

  • ticker2.json:

    {“test”:{“msgOne”:[“ticker2远程一”,“ticker2远程二”,“ticker2远程三”],“msgTwo”:“Remote2”,“msgThree”:“Remote3”}}

  • ticker3.json:

    {“测试”:{“msgOne”:[“ticker3远程一”,“ticker3远程二”,“ticker3远程三”],“msgTwo”:“Remote2”,“msgThree”:“Remote3”}}

于 2013-05-17T16:14:07.523 回答