【问题标题】:Looping through an ajax callback with jquery使用 jquery 循环通过 ajax 回调
【发布时间】:2013-05-16 16:59:11
【问题描述】:

我正在尝试循环通过 ajax 调用 3 个不同的 json 文件,这些文件具有相同的命名约定和结构(但数据略有不同)。自从我在论坛 (jQuery ajax success callback function definition) 中阅读 Alnitak 的回复以来,我一直在使用延迟对象而不是成功选项,这样我的 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 数组写入屏幕?感谢任何帮助和建设性的 cmets。另外,我需要保持 ajax 调用异步,因为我将来会使用 jsonp 数据类型。

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

【问题讨论】:

    标签: javascript ajax jquery


    【解决方案1】:

    问题是你的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.. 它会工作

    【讨论】:

    • 感谢您的帮助。但是,似乎我没有得到我想要的最终结果。它只打印出第一个 json 文件结果。
    • if(this.myJ&lt;2){ 之前检查alert(this.myJ) 如果它未定义然后尝试$(this).myJ... 你注意到ajax 调用的变化了吗? myJ: m这就是关键
    • 警报(this.mJ)给出:0,这是正确的,但是,您提供的代码只会从第一个 json 文件中打印出所需的数据。如果我添加 getData(1).done(handleData);在代码的末尾,它仍然只会打印第一个 json 文件中的数据,而不是我指定的第二个。我真正想要的是能够连续打印出所有三个 json 文件中的数据。出于某种原因,它一直挂断第一个 ajax 调用(据我所知)。还有其他想法吗?
    • 我会在function handleData(data){ 第一行中建议alert("here"); alert(data.test.msgOne)(data.test.msgOne[0])...看看您是否正确地获得了第二个ajax 请求的结果...您所说的可能会发生如果第一个请求成功并返回 jsondata.test.msgOne 但第二个请求失败......或者没有以正确格式返回 json,而不是 data.test.msgOne 返回 data.test.msgONE 然后 javascript 将失败,您只会看到 1 个结果印刷中
    • 警报有效。我最终只使用了一个警报,即 alert(data.test.msgOne) 语句,并在上面代码的最后一个语句周围放置了一个 for 循环: getData(i).done(handleData) (将 0 替换为索引变量,i)。当我在没有警报(Data.test.msgOne 语句)的情况下执行此操作时,我只会打印第一组 json 数据,但如果我包含警报,则所有内容都会正确发出警报并打印到屏幕上!太棒了!但问题仍然存在,有没有办法让所有内容都正确输出到屏幕上而不会发出警报语句?
    【解决方案2】:

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

    • ticker1.json:

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

    • ticker2.json:

      { “测试”: { “味精”:[ “ticker2远程一号”, "ticker2 远程二", “ticker2 远程三” ], "msgTwo": "Remote2", "msgThree": "Remote3" } }

    • ticker3.json:

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

    【讨论】:

      【解决方案3】:

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

      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 推送到数组中。尝试this link 获取将deferred 对象数组传递给$.when() 的示例。

      另一个修改

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

      【讨论】:

      • 我不确定这是否会起作用,正如您在此处概述的那样。 result1,2,3 未定义。
      • 好吧,当我在它之后放置一个警报时,request1 甚至没有按定义出现:alert("Request1 is: " + request1);然后产生“对象对象”作为它的值。
      • 如果你警告值并获得“对象对象”,那么它就被定义了。 Javascript 对象只是没有非常有用的字符串输出。
      • 我的错。谢谢。那么我怎样才能看到那个对象中的内容呢?我已经尝试按照我通常的预期访问它,但我得到它没有定义。例如:request1.test.msgOne[1] 不工作。
      • 尝试使用 result1 而不是 request1。
      猜你喜欢
      • 2012-03-03
      • 2015-04-28
      • 1970-01-01
      • 2014-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-11
      • 1970-01-01
      相关资源
      最近更新 更多