JQuery Ajax/обратный вызов .each, следующий «каждый» запуск до завершения ajax

Привет, приведенный ниже Javascript вызывается, когда я отправляю форму. Сначала он отделяет кучу URL-адресов от текстовой области, а затем:

1) Добавляет строки в таблицу для каждого URL-адреса, а в последнем столбце (столбце «Статус») написано «Не начато».
2) Опять он перебирает каждый URL-адрес, сначала он делает вызов ajax. чтобы проверить статус (status.php), который вернет процент от 0 до 100.
3) В том же цикле он запускает фактический процесс через ajax (process.php), когда процесс завершен ( принимая во внимание непрерывные обновления статуса), затем в столбце статуса будет указано «Завершено» и выход из auto_refresh.
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>");
          }
        });

    });

}

person StuR    schedule 16.12.2010    source источник


Ответы (4)


Вам нужно запустить несколько асинхронных действий последовательно, верно? Я бы построил массив функций для выполнения и запустил его через помощник последовательности.

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)));
    })();
}
person Michiel Kalkman    schedule 16.12.2010
comment
Идеально, как раз то, что я хотел. Спасибо. - person StuR; 16.12.2010

AJAX является асинхронным.

Это именно то, что должно произойти.

Вместо использования each вы должны отправить следующий запрос AJAX в обработчике завершения предыдущего.

person SLaks    schedule 16.12.2010

Вы также можете настроить синхронный запуск AJAX, используя свойство «async». Добавьте следующее:

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

Справочник по API AJAX здесь. Обратите внимание, что это заблокирует браузер до завершения запроса.

Я предпочитаю подход в ответе SLaks (придерживаясь асинхронного поведения). Однако это зависит от вашего приложения. Соблюдайте осторожность.

person jthompson    schedule 16.12.2010
comment
Не делайте этого. Он полностью заморозит браузер, пока сервер не ответит. - person SLaks; 16.12.2010
comment
Ответ был добавлен для полноты, так как опция доступна. Лучше придерживаться асинхронных вызовов. - person jthompson; 16.12.2010

Я бы дал тот же ответ, что и этот 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);

    }       
}
person Sandeepan Nath    schedule 16.12.2010