开发者

How to implement sequntial iteration with asynchronous code

开发者 https://www.devze.com 2023-01-06 22:44 出处:网络
I want to implement sequential upload of files (with XMLHttpRequest level2) to server. Got bunch of DOM elements with File attached (FileAPI - W3C draft). I want to upload in sequence (one after anoth

I want to implement sequential upload of files (with XMLHttpRequest level2) to server. Got bunch of DOM elements with File attached (FileAPI - W3C draft). I want to upload in sequence (one after another), but XMLHttpRequest works asynchronously. Little code sample:

$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 F开发者_C百科ormData

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

Problem with this code is, that FOR cycle iterates independently on upload proces of file. So more paralel uploads are started:

  • iteration starts,
    • xhr is created/populated,
    • upload begins,
    • new iteration

This design create new xhr object even if previous upload is not finished. But I still want to hold asynch paradigm (no browser block, progress events, etc.) of upload. Just cannot figure out, how to wait for current upload to finish and then start new upload cycle.

Any ideas?


You can create a stack and handle the requests recursively, also reusing the same request object.

I know, it rocks! :) Here is your code:

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

})();


I have a useful javascript library for this sort of thing: http://caolanmcmahon.com/async.html

You could easily rewrite this code to use forEachSeries or mapSeries... along the lines of:

async.forEachSeries(thumbnails, function(thumb, callback){
    var xhr = new XMLHttpRequest();
    xhr.upload.onload = function(ev){ callback(); };
    ...
});
0

精彩评论

暂无评论...
验证码 换一张
取 消