2010-07-14 26 views
0

我想实现文件(使用XMLHttpRequest level2)到服务器的顺序上载。附上File附带一堆DOM元素(FileAPI - W3C草案)。我想依次上传(一个接一个),但XMLHttpRequest异步工作。小代码示例:如何使用异步代码实现sequntial迭代

$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

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

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

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

})(); 
+0

我认为这将是解决方案。谢谢sooooooooooooo了。 – srigi 2010-07-14 13:57:18

+0

@srigi np男人,保持冷静,保持锐利:) – galambalazs 2010-07-14 13:59:49

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(); }; 
    ... 
});