如何使用异步代码实现顺序迭代

时间:2010-07-14 13:25:05

标签: javascript events asynchronous

我想实现向服务器顺序上传文件(使用XMLHttpRequest level2)。获得了附带File的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循环在文件的上传过程中独立迭代。所以开始更多的paralel上传:

  • 迭代开始,
    • xhr已创建/填充,
    • 上传开始,
    • 新迭代

即使先前的上传未完成,此设计也会创建新的xhr对象。但是我仍然希望保持上传的asynch范例(没有浏览器块,进度事件等)。只是想不通,如何等待当前上传完成然后开始新的上传周期。

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

您可以创建堆栈并处理递归请求,同时重复使用相同的请求对象。

我知道,岩石! :)这是你的代码:

// 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 :(得分:1)

我有一个有用的javascript库用于此类事情: http://caolanmcmahon.com/async.html

您可以轻松地重写此代码以使用forEachSeries或mapSeries ......按照以下方式:

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