Как реализовать последовательную итерацию с асинхронным кодом - PullRequest
0 голосов
/ 14 июля 2010

Я хочу реализовать последовательную загрузку файлов (с уровнем XMLHttpRequest2) на сервер. Получил кучу элементов DOM с прикрепленным файлом (FileAPI - W3C черновик). Я хочу загрузить в последовательности (один за другим), но XMLHttpRequest работает асинхронно. Маленький пример кода:

$thumbnails = $('queue').find('.item');
for (var i = 0, len = thumbnails.length; i < len; i++) {
  var xhr = new XMLHttpRequest();
  xhr.upload.onload = function(ev){}; // fires on upload complete
  var fd = new FormData
  fd.append('Files['+i+']', $thumbnails[i].file) // insert atached File to FormData

  xhr.open("POST", 'server_url', true) // last true means "use asynch rq"
  xhr.send(fd)
}

Проблема с этим кодом в том, что цикл FOR повторяется независимо от процесса загрузки файла. Таким образом, начинаются дополнительные загрузки паралелей:

  • итерация начинается,
    • xhr создан / заполнен,
    • загрузка начинается,
    • новая итерация

Этот дизайн создает новый объект xhr, даже если предыдущая загрузка не была завершена. Но я все еще хочу придерживаться асинхронной парадигмы загрузки (без блокировки браузера, событий прогресса и т. Д.). Просто не могу понять, как дождаться окончания текущей загрузки и начать новый цикл загрузки.

Есть идеи?

Ответы [ 2 ]

2 голосов
/ 14 июля 2010

Вы можете создать стек и обрабатывать запросы рекурсивно , также используя тот же объект запроса.

Я знаю, это качается !:) Вот ваш код:

// last in, first out.
var stack = [];

$('queue').find('.item').each(function(i, el){
    // insert atached File to FormData
    var fd = new FormData();
    fd.append('Files['+i+']', el.file);
    stack.push(fd);
});

var xhr = new XMLHttpRequest();

(function recur() {

  // fires on upload complete
  xhr.upload.onload = function(ev) {
    // do recursion until the stack is not empty
    if (stack.length) recur();
  };

  // send an asynchronous POST request
  xhr.open("POST", 'server_url', true);
  xhr.send(stack.shift());

})();
1 голос
/ 15 июля 2010

У меня есть полезная библиотека javascript для такого рода вещей: http://caolanmcmahon.com/async.html

Вы можете легко переписать этот код, чтобы использовать forEachSeries или mapSeries ... в соответствии с:

async.forEachSeries(thumbnails, function(thumb, callback){
    var xhr = new XMLHttpRequest();
    xhr.upload.onload = function(ev){ callback(); };
    ...
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...