【问题标题】:execute code after AJAX loop finishedAJAX 循环结束后执行代码
【发布时间】:2018-07-19 09:12:46
【问题描述】:

我有一个 AJAX 调用,该调用被称为“i”次。我只想在最后一个 AJAX processData 回调函数完成后执行其余代码(它将 .csv 的值填充到一个名为“lines”的数组中,并且在所有迭代完成后我需要完成的数组)。到目前为止,它只能通过使用“setTimeout()”来工作,这不是一个好的解决方案

for (var i = 0; i < options.length; i++) {
    (function(index) {
        $.ajax({
            type: "GET",
            url: options[index] + ".csv",
            dataType: "text",
            success: function(data) {
                processData(data, options[index], type)
            }
        });
    })(i);
}
setTimeout(function() {
    getAveragePercentages(lines);
}, 500)

【问题讨论】:

  • 我认为“其余代码”是您的 getAveragePercentage(lines) 代码?如果是这样,如果你只是把它放在你的 for 循环之外,那应该可以工作。你如何开始你的 for 循环?通过单击按钮?
  • 它从单击按钮开始,正确。如果我把它放在外面,“getAveragePercentages()”的代码将在 ajax 回调完成之前执行
  • @ChristopherSupertramp 这不起作用,因为循环将在所有 ajax 调用完成之前完成。 Ajax 本质上是异步的
  • Promise.all() 可能会有所帮助

标签: javascript jquery ajax iife


【解决方案1】:

您可以使用 JavaScript 承诺功能。

在 Promise 中发出 AJAX 请求。 创建一个包含所有这些承诺的数组。

Promise.all 将在所有 Promise 解决后执行。

var promiseArr = [];
for (var i = 0; i < options.length; i++) {
    var promise = new Promise(function(resolve, reject) {
        (function(index) {
            $.ajax({
                type: "GET",
                url: options[index] + ".csv",
                dataType: "text",
                success: function(data) {
                    processData(data, options[index], type); resolve('outputIfany')
                }
            });
        })(i);
    });
    promiseArr.push(promise);
}
Promise.all(promiseArr).then(function(values) {
    getAveragePercentages(lines);
});

【讨论】:

  • 这样的话,就不用每次都比较了。
  • 这听起来有道理,我试试看!
  • 就像一个魅力。非常感谢 - 从现在开始我会记住这个功能!
【解决方案2】:
for (var i = 0; i < options.length; i++) {
    (function (index) {
        $.ajax({
            type: "GET",
            url: options[index] + ".csv",
            dataType: "text",
            success: function (data) {
                processData(data, options[index], type)
            }
        });
        counter = counter + 1;
    })(i);
    if (i == options.length) {
        getAveragePercentages(lines);
    }
}

【讨论】:

    【解决方案3】:

    你可以这样做。

    上一次循环成功后调用函数

    var totalRec = options.length;
    for(var i=0;i<options.length;i++){
        (function(index){       
            $.ajax({ 
                type: "GET",
                url: options[index]+".csv",
                dataType: "text",
                success: function(data) {processData(data, options[index], type)
    
    
               if(i == (totalRec-1)){
                  getAveragePercentages(lines);
               }
            }
            });
        })(i);
    }
    

    var totalRec = options.length;
        for(var i=0;i<options.length;i++){
            (function(index){       
                $.ajax({ 
                    type: "GET",
                    url: options[index]+".csv",
                    dataType: "text",
                    success: function(data) {processData(data, options[index], type)
    
    
                }
                });
            })(i);
    
         if(i == (totalRec-1)){
              getAveragePercentages(lines); // gets called only when condition is true
          }
        }
    

    【讨论】:

      【解决方案4】:

      使用 setTimeOut 来等待 ajax 调用不是一个好习惯,根据我的经验,我一直在使用递归函数来执行此操作,在您的情况下,您可以执行以下操作:

      var counter = 0;
      function main()
      {
          counter = 0;
          doAjaxCall(counter);
      }
      
      function doAjaxCall(counter)
      {
          (function(index){       
                      $.ajax({ 
                          type: "GET",
                          url: options[index]+".csv",
                          dataType: "text",
                          success: function(data) {
                             processData(data, options[index], type);
                             if(counter < options.length)
                             {
                                 counter++;
                                 doAjaxCall(counter); //We call the same function but with the next index
                             }
                             else
                             {
                                //The loop finished, countinue code after your for loop
                             }
                          }
                      });
                  })(i);
      }
      

      【讨论】:

      • 我看到processData也是一个回调函数,这种情况下你可以把if(counter
      • 需要注意的是,这将按顺序执行,这意味着下一个网络调用只有在前一个网络调用完成并处理后才会开始。除非processData 实际上需要按顺序调用,否则效率很低。
      【解决方案5】:

      在调用你的函数之前设置一个计数器并检查它的值

      $("#counter").html("0");
      for(var i=0;i<options.length;i++){
                  (function(index){       
                      $.ajax({ 
                          type: "GET",
                          url: options[index]+".csv",
                          dataType: "text",
                          success: function(data) {
                          processData(data, options[index], type)
                          var counter = $("#counter").html();
                          if( counter == options.length ){
                            getAveragePercentages(lines);
                          }
                           $("#counter").html(counter+1);
                         }
                      });
      
                  })(i);
              }
      

      【讨论】:

      • 问题是我不知道最终的计数器有多大,选项可能有不同的长度。
      • @user3024814 然后使用options.length 进行比较..检查我的更新答案
      • 此检查将失败,因为它只检查一次,如果此时 counter 不在 option.length 上(它不会),它将跳过。我不想让循环无情地检查
      • 您是对的,已编辑,将检查移至循环内部。至于第二点,这就是循环的工作方式。它会一直跳到满足条件为止。此检查只会触发对于每个 ajax 请求.. 比 setTimeout 函数更好。
      • 但这不是它的工作方式。我们需要等待最后一个回调(processData)成功,这是异步的,这意味着$.ajax()调用之后的代码不会等待回调完成。
      【解决方案6】:

      我添加了一个函数作为参数。加载完成后AJAX调用该函数。

      function loadDoc(call_back_func) {
        const xhttp = new XMLHttpRequest();
        xhttp.onload = function() {
          json_data = JSON.parse(this.responseText);
          call_back_func();
        }
        xhttp.open("GET", "kanban_personal_template.json");
        xhttp.send();
      }
      
      function load_call_back()
      {
          console.log(json_data);
      }
      loadDoc(load_call_back);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-10
        • 1970-01-01
        • 2022-11-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多