简体   繁体   English

jQuery Ajax / .each回调,在ajax完成之前接下来的'each'触发

[英]jQuery Ajax / .each callback, next 'each' firing before ajax completed

Hi the below Javascript is called when I submit a form. 嗨,当我提交表单时,会调用以下Javascript。 It first splits a bunch of url's from a text area, it then: 它首先从文本区域中分割出一堆url,然后:

1) Adds lines to a table for each url, and in the last column (the 'status' column) it says "Not Started". 1)为每个网址添加一个表格行,并在最后一列(“状态”列)中显示“未启动”。
2) Again it loops through each url, first off it makes an ajax call to check on the status (status.php) which will return a percentage from 0 - 100. 2)再次循环遍历每个URL,首先关闭它进行ajax调用以检查状态(status.php),该状态将返回0-100的百分比。
3) In the same loop it kicks off the actual process via ajax (process.php), when the process has completed (bearing in the mind the continuous status updates), it will then say "Completed" in the status column and exit the auto_refresh. 3)在同一个循环中,它通过ajax(process.php)启动实际进程,当进程完成时(记住连续状态更新),它将在状态列中说“已完成”并退出自动刷新。
4) It should then go to the next 'each' and do the same for the next url. 4)然后它应该转到下一个'each'并为下一个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>");
          }
        });

    });

}

What you want is to run several asynchronous actions in sequence , right? 你想要的是按顺序运行几个异步动作,对吗? I'd build an array of the functions to execute and run it through a sequence helper. 我将构建一个函数数组来执行并通过序列帮助程序运行它。

https://github.com/michiel/asynchelper-js/blob/master/lib/sequencer.js 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();
          }
        });
    });
  }
);

As you can see, we build an array of scoped functions that take an arbitrary callback as an argument. 如您所见,我们构建了一个范围函数数组,它们将任意回调作为参数。 A sequencer will run them in order for you. 音序器将为您运行它们。

Use the sequence helper from the github link and run, 使用github链接中的序列助手并运行,

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

It is, btw, possible to define sequencer functions in a few lines of code. 顺便说一下,可以在几行代码中定义音序器功能。 For example, 例如,

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

AJAX is asynchronous . AJAX是异步的

That's exactly what's supposed to happen. 这正是应该发生的事情。

Instead of using each , you should send the next AJAX request in the completion handler of the previous one. 您应该在前一个完成处理程序中发送下一个AJAX请求,而不是使用each请求。

I would give the same answer as this jquery json populate table 我会给出与jquery json populate表相同的答案

This code will give you a little idea how to use callback with loops and ajax. 这段代码将为您提供如何使用循环和ajax回调的一些想法。 But I have not tested it and there will be bugs. 但我没有测试它,会有bug。 I derived the following from my old code:- 我从旧代码中得出以下内容: -

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);

    }       
}

You can also set AJAX to run synchronously using the "async" property. 您还可以使用“async”属性将AJAX设置为同步运行。 Add the following: 添加以下内容:

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

AJAX API reference here . 这里有 AJAX API参考。 Note that this will lock the browser until the request completes. 请注意,这将锁定浏览器,直到请求完成。

I prefer the approach in SLaks answer (sticking with asynchronous behavior). 我更喜欢SLaks中的方法回答(坚持异步行为)。 However, it does depend on your application. 但是,它取决于您的应用程序。 Exercise caution. 谨慎行事。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM