Зацикливание через jQuery Отложенные после того, как все promises были вызваны
В настоящее время я пытаюсь создать загрузчик файлов с помощью файла HTML5 FileAPI. Файл Uploader должен обрабатывать несколько файлов и показывать предварительный просмотр изображений, если файл является изображением.
так как класс FileReader работает асинхронно, я хочу подождать, пока все файлы не будут прочитаны. Поэтому я использую Deferreds.
Метод, который читает файл, возвращает обещание. Другой метод обрабатывает все файлы и выталкивает все promises в массив. Затем я применяю метод then(), как только все promises были добавлены в мой массив.
Теперь к моей проблеме. Поскольку метод then() вызывается только один раз, когда я получил все promises. У меня нет возможности обработать каждое обещание. Я хочу сделать, чтобы пропустить все мои promises, когда они все там, и вернет результат.
Это мой 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 Object 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? Разве они не должны использоваться так, как я пытаюсь сделать, и есть ли более элегантный способ достичь моей цели?
Ответы
Ответ 1
Использую ли я неправильный подход для отсрочек и promises?
Да. При асинхронном обратном вызове вы не должны обращаться к promises
, а только к аргументам обратного вызова. Возвратное обещание $.when
разрешает с массивом параметров .resolve()
для каждого из promises в массиве - вы можете петля над объектом arguments
для доступа к результатам:
$.when.apply($, promises).then(function () {
for (var i = 0; i < arguments.length; i++) {
var singleresult = arguments[i][0];
console.log(singleresult);
}
});
Ответ 2
вы можете использовать объект аргументов для ссылки на все значения, возвращаемые объектами обещания
$.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);
}
});
Ответ 3
Я вижу, что вы приняли ответ, но вам может быть интересно узнать, что ваш метод 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]);
});
});
},
Конечно, это снова усложнится, когда вы обработаете обработку результатов, но это должно дать вам краткую основу.