我目前正在尝试使用HTML5 FileAPI构建文件上传器。如果文件是图像,文件上传器应该处理多个文件并显示图像预览。
由于FileReader类异步工作,我想等到所有文件都被读取。因此我使用Deferreds。
读取文件的方法正在返回一个promise。另一种方法遍历所有文件并将所有promises推送到数组中。然后,我将所有promises添加到我的数组后应用then()方法。
现在我的问题。因为then()方法只被称为一次,所以我得到了所有的承诺。我没有机会处理每一个承诺。我想要做的是,一旦它们全部存在并且返回结果,就要遍历我的所有承诺。
这是我的 FileProcessor 对象
read: function(file) {
var reader = new FileReader();
var deferred = $.Deferred();
reader.onload = function(event){
deferred.resolve(event.target.result);
};
reader.onerror = function() {
deferred.reject(this);
}
if(/^image/.test(file.type))
reader.readAsDataURL(file);
return deferred.promise();
},
这里有 FileManager 对象的handleFileSelect()方法,它应该调用FileProcessor.read()方法。
handleFileSelect: function(e){
var $fileList = $('#file-list');
var files = e.target.files;
var promises = []; //Promises are going to be stored here
var filestring = '';
var processedFile;
// Loop trough all selected files
for(var i = 0; i < files.length; i++){
// Store the promise in a var...
processedFile = FileProcessor.read(files[i]);
// And push it into the array where the promises are stored
promises.push(processedFile);
}
// Once all deferreds have been fired...
$.when.apply(window, promises).then(function(){
for(var i = 0; i < promises.length; i++){
// PROBLEM HERE: I need to get the
// result from my resolved Deferred
// of every single promise object
console.log(promises[i]);
}
});
},
我是否使用了错误的方法来推迟和承诺?它们不应该像我想要的那样被使用,是否有更优雅的方式来达到我的目的?
答案 0 :(得分:7)
我是否使用了错误的方法来推迟和承诺?
是。在异步回调中,您不应该访问promises
,而只能访问回调参数。 $.when
的返回承诺确实通过数组中每个promise的.resolve()
参数数组来解析 - 您可以遍历arguments
object来访问结果:
$.when.apply($, promises).then(function () {
for (var i = 0; i < arguments.length; i++) {
var singleresult = arguments[i][0];
console.log(singleresult);
}
});
答案 1 :(得分:2)
您可以使用arguments object来引用promise对象返回的所有值
$.when.apply($, promises).then(function () {
for (var i = 0; i < arguments.length; i++) {
var data = arguments[i][0];
// PROBLEM HERE: I need to get the
// result from my resolved Deferred
// of every single promise object
console.log(data);
}
});
答案 2 :(得分:1)
我看到你已经接受了答案,但您可能想知道您的handleFileSelect
方法可以大大简化如下
handleFileSelect: function(e) {
var promises = $.map(e.target.files, function(file) {
return FileProcessor.read(file);
});
$.when.apply(window, promises).then(function() {
$.each(arguments, function(i, a) {
console.log(a[0]);
});
});
},
当你充实结果处理时,它会再次变得更复杂,但这应该给你一个很简洁的基础。