在所有承诺被调用之后,通过jQuery Deferreds循环

thp*_*hpl 1 javascript jquery deferred jquery-deferred

我目前正在尝试使用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();
},
Run Code Online (Sandbox Code Playgroud)

这里是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]);
        }
    });

},
Run Code Online (Sandbox Code Playgroud)

我是否使用了错误的方法来推迟和承诺?它们不应该像我想要的那样被使用,是否有更优雅的方式来实现我的目的?

Ber*_*rgi 7

我是否使用了错误的方法来推迟和承诺?

是.在异步回调中,您不应该访问promises,而只能访问回调参数.返回的承诺$.when确实解决了数组中.resolve()每个promise 的参数数组 - 你可以遍历arguments对象来访问结果:

$.when.apply($, promises).then(function () {
    for (var i = 0; i < arguments.length; i++) {
        var singleresult = arguments[i][0];
        console.log(singleresult);
    }
});
Run Code Online (Sandbox Code Playgroud)