簡體   English   中英

在調用所有承諾后循環遍歷 jQuery Deferreds

[英]Looping through jQuery Deferreds after all promises have been called

我目前正在嘗試使用 HTML5 FileAPI 構建文件上傳器。 如果文件是圖像,文件上傳器應該處理多個文件並顯示圖像預覽。

由於 FileReader 類異步工作,我想等到所有文件都被讀取。 因此我正在使用延遲。

讀取文件的方法正在返回一個承諾。 另一種方法遍歷所有文件並將所有承諾推送到一個數組中。 然后,一旦所有承諾都添加到我的數組中,我就會應用 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]);
        }
    });

},

我是否對延遲和承諾使用了錯誤的方法? 難道它們不應該像我試圖做的那樣使用,有沒有更優雅的方式來實現我的目的?

我是否對延遲和承諾使用了錯誤的方法?

是的。 在異步回調中,您不應訪問promises ,而只能訪問回調參數。 $.when .resolve()的返回承諾確實使用數組中每個承諾的.resolve()參數數組解析 - 您可以遍歷arguments對象以訪問結果:

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

您可以使用arguments 對象來引用 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);
    }
});

我看到你已經接受了一個答案,但你可能想知道你的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]);
        });
    });
},

當然,當您充實結果處理時它會再次變得更加復雜,但這應該為您提供一個很好的簡潔基礎。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM