Looping a través de jQuery Deferreds después de que se hayan llamado todas las promesas

Actualmente estoy intentando crear un File Uploader usando HTML5 FileAPI. Se supone que File Uploader maneja varios archivos y muestra vistas previas de imágenes si el archivo es una imagen.

dado que la clase FileReader funciona de forma asíncrona, quiero esperar hasta que se hayan leído todos los archivos. Por lo tanto, estoy usando Deferreds.

Un método que lee el archivo devuelve una promesa. Otro método recorre todos los archivos y coloca todas las promesas en una matriz. Luego aplico el método then () una vez que todas las promesas se han agregado a mi matriz.

Ahora a mi problema. Como el método then () solo se llama una vez , cuando obtuve todas las promesas. No tengo oportunidad de procesar cada promesa. Lo que quiero hacer es recorrer todas mis promesas una vez que estén todas allí y devolver el resultado.

Este es mi Objeto 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(); }, 

Y aquí viene el método handleFileSelect () del objeto FileManager que supuestamente llama al método 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]); } }); }, 

¿Estoy usando el enfoque equivocado para diferir y promesas? ¿No se supone que deben usarse como lo estoy intentando hacer y hay una forma más elegante de lograr mi propósito?

¿Estoy usando el enfoque equivocado para diferir y promesas?

Sí. En la callback asíncrona no debe acceder a las promises , sino solo a los argumentos de callback. La promesa de retorno de $.when se resuelve con una matriz de los parámetros .resolve() para cada una de las promesas en la matriz – puede recorrer el objeto arguments para acceder a los resultados:

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

puede usar el objeto arguments para referir todos los valores devueltos por los objetos prometidos

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

Veo que has aceptado una respuesta, pero te gustaría saber que el método handleFileSelect se puede simplificar significativamente de la siguiente manera

 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]); }); }); }, 

Por supuesto, se volverá más complicado de nuevo cuando analices el manejo del resultado, pero esto debería darte una buena base concisa.