jQuery Ajax / .each callback, next 'each'

2019-02-10 09:31发布

Hi the below Javascript is called when I submit a form. It first splits a bunch of url's from a text area, it then:

1) Adds lines to a table for each url, and in the last column (the 'status' column) it says "Not Started".
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.
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.
4) It should then go to the next 'each' and do the same for the next 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>");
          }
        });

    });

}

4条回答
The star\"
2楼-- · 2019-02-10 10:08

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

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,

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)));
    })();
}
查看更多
贪生不怕死
3楼-- · 2019-02-10 10:08

I would give the same answer as this jquery json populate table

This code will give you a little idea how to use callback with loops and ajax. But I have not tested it and there will be bugs. 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);

    }       
}
查看更多
你好瞎i
4楼-- · 2019-02-10 10:10

You can also set AJAX to run synchronously using the "async" property. Add the following:

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

AJAX API reference here. Note that this will lock the browser until the request completes.

I prefer the approach in SLaks answer (sticking with asynchronous behavior). However, it does depend on your application. Exercise caution.

查看更多
We Are One
5楼-- · 2019-02-10 10:14

AJAX is asynchronous.

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.

查看更多
登录 后发表回答