【问题标题】:jQuery Ajax / .each callback, next 'each' firing before ajax completedjQuery Ajax / .each 回调,在 ajax 完成之前下一个“每个”触发
【发布时间】:2010-12-16 15:48:12
【问题描述】:

您好,当我提交表单时,会调用以下 Javascript。它首先从文本区域中拆分出一堆 url,然后:

1) 将行添加到每个 url 的表中,并在最后一列(“状态”列)中显示“未开始”。
2) 再次循环遍历每个 url,首先它进行 ajax 调用以检查状态 (status.php),该状态将返回 0 - 100 之间的百分比。
3) 在同一个循环中,它通过 ajax (process.php) 启动实际进程,当进程完成时(记住不断更新的状态),它会在状态列中显示“已完成”并退出自动刷新。
4) 然后它应该转到下一个“每个”并为下一个 url 做同样的事情。

function formSubmit(){

    var lines = $('#urls').val().split('\n');

    $.each(lines, function(key, value) {
        $('#dlTable tr:last').after('<tr><td>'+value+'</td><td>Not Started</td></tr>');
    });

    $.each(lines, function(key, value) {

        var auto_refresh = setInterval( function () {
            $.ajax({
              url: 'status.php',
              success: function(data) {
            $('#dlTable').find("tr").eq(key+1).children().last().replaceWith("<td>"+data+"</td>");
              }
            });
        }, 1000);

        $.ajax({
          url: 'process.php?id='+value,
          success: function(msg) {
        clearInterval(auto_refresh);
        $('#dlTable').find("tr").eq(key+1).children().last().replaceWith("<td>completed rip</td>");
          }
        });

    });

}

【问题讨论】:

    标签: javascript jquery ajax asynchronous each


    【解决方案1】:

    您想要的是按顺序运行几个异步操作,对吗?我会构建一个函数数组来执行并通过序列助手运行它。

    https://github.com/michiel/asynchelper-js/blob/master/lib/sequencer.js

    var actions = [];
    $.each(lines, function(key, value) {
    
        actions.push(function(callback) {
          $.ajax({
              url: 'process.php?id='+val,
              success: function(msg) {
                clearInterval(auto_refresh);
    
                //
                // Perform your DOM operations here and be sure to call the
                // callback!
                //
    
                callback();
              }
            });
        });
      }
    );
    

    如您所见,我们构建了一个范围函数数组,这些函数将任意回调作为参数。定序器会按顺序为您运行它们。

    使用 github 链接中的序列助手并运行,

    var sequencer = new Sequencer(actions);
    sequencer.start();
    

    顺便说一句,可以在几行代码中定义定序器函数。例如,

    function sequencer(arr) {
        (function() {
            ((arr.length != 0) && (arr.shift()(arguments.callee)));
        })();
    }
    

    【讨论】:

    • 完美,正是我所追求的。谢谢。
    【解决方案2】:

    AJAX 是异步的

    这正是应该发生的事情。

    您应该在前一个的完成处理程序中发送下一个 AJAX 请求,而不是使用each

    【讨论】:

      【解决方案3】:

      您还可以使用“async”属性将 AJAX 设置为同步运行。添加以下内容:

      $.ajax({ "async": false, ... other options ... });
      

      AJAX API 参考 here。请注意,这将锁定浏览器,直到请求完成。

      我更喜欢 SLaks 回答中的方法(坚持异步行为)。但是,它确实取决于您的应用程序。谨慎行事。

      【讨论】:

      • 不要这样做。它将完全冻结浏览器,直到服务器回复。
      • 答案是为了完整性而添加的,因为该选项可用。坚持使用异步调用会更好。
      【解决方案4】:

      我会给出与jquery json populate table相同的答案

      此代码将让您了解如何将回调与循环和 ajax 一起使用。但是我没有测试过,会有错误。我从旧代码中得出以下内容:-

      var processCnt; //Global variable - check if this is needed
      function formSubmit(){
      
          var lines = $('#urls').val().split('\n');
      
          $.each(lines, function(key, value) {
              $('#dlTable tr:last').after('<tr><td>'+value+'</td><td>Not Started</td></tr>');
          });
      
          completeProcessing(lines ,function(success)
          {
                 $.ajax({
                url: 'process.php?id='+value,
                success: function(msg) {
                      $('#dlTable').find("tr").eq(key+1).children().last().replaceWith("<td>completed rip</td>");
                }
              });
      
      
          });
      
      
      }
      
      //Following two functions added by me
      function completeProcessing(lines,callback)
      {
          processCnt= 0;
          processingTimer = setInterval(function() { singleProcessing(lines[processCnt],function(completeProcessingSuccess){ if(completeProcessingSuccess){ clearInterval(processingTimer); callback(true); }})}, 1000);    
      
      }
      
      
      function singleProcessing(line,callback)
       {
          key=processCnt;
          val = line;
          if(processCnt < totalFiles)
          { //Files to be processed
      
              $.ajax({
                        url: 'status.php',
                          success: function(data) {
                                 $('#dlTable').find("tr").eq(key+1).children().last().replaceWith("<td>"+data+"</td>");
                            processCnt++; 
                            callback(false); 
      
                          }
                      });
          }
          else
          {
              callback(true);
      
          }       
      }
      

      【讨论】:

        猜你喜欢
        • 2016-12-13
        • 1970-01-01
        • 2013-09-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多