javascript - sincronas - ¿Cuál es la forma más limpia de convertir Array of JQuery Promises en una promesa JQuery de una matriz?
promise para javascript (2)
Me encuentro con la situación en la que tengo varias JQuery Promises en una matriz
var arrayOfPromises = [ $.Deferred(), $.Deferred(), $.Deferred(), $.Deferred() ]
y necesita convertirlo en una promesa jQuery de una matriz
var promiseOfArray = someTransform(arrayOfPromises)
dónde
promiseOfArray.done(function(anArray){
alert(anArray.join(","));
});
crea una alerta con texto
resultado1, resultado2, resultado3, resultado4
Actualmente defino someTransform
en coffeescript como
someTransform = (arrayOfPromises) ->
$.when(arrayOfPromises...).pipe (promises...) ->
promises
que se transforma en el siguiente javascript
var someTransform,
__slice = [].slice;
someTransform = function(arrayOfPromises) {
return $.when.apply($, arrayOfPromises).pipe(function() {
var promises;
promises = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return promises;
});
};
Aquí hay un jsFiddle del resultado que estoy buscando.
Me preguntaba si existe una forma mejor (más corta, más limpia) de definir someTransform
para lograr el mismo resultado.
Puede simplemente aplicar la matriz como argumentos a $.when
.
var promiseOfArray = $.when.apply($, arrayOfPromises);
Para que el uso de este sea más claro, me gusta agregar un método a $
:
$.whenall = function(arr) { return $.when.apply($, arr); };
Ahora puedes hacer:
$.whenall([deferred1, deferred2, ...]).done(...);
Actualización: de forma predeterminada, el manejador done
obtiene cada resultado pasado como un argumento separado; no obtienes una variedad de resultados.
Como necesita manejar un número arbitrario de Deferidos, puede usar el objeto especial de arguments
implícitos para recorrer los resultados.
$.whenall([d1, d2, ...]).done(function() {
for (var i = 0; i < arguments.length; i++) {
// do something with arguments[i]
}
});
Si realmente desea unirse al resultado de cadena de todos sus Deferreds, podemos emplear un hacker de matriz pequeña. arguments
es similar a una Array
, pero no es una Array
:
$.whenall([d1, d2, ...]).done(function() {
alert(Array.prototype.join.call(arguments, '',''));
});
Si desea devolver una matriz de resultados a su devolución de llamada done
, podemos ajustar whenall
para hacerlo :
$.whenall = function(arr) {
return $.when.apply($, arr).pipe(function() {
return Array.prototype.slice.call(arguments);
});
};
También me molestó mucho escribir siempre la línea "fea" $.when.apply
cuando necesitamos invocarla en múltiples promesas. ¡Pero Function.prototype.bind
para el rescate!
var when = Function.prototype.apply.bind( jQuery.when, null );
Ahora, podemos simplemente llamar
when( someArrayWithPromises ).done(function() {
});
Function.prototype.bind
es parte de ES5 y está ampliamente disponible en todos los navegadores. Hay un montón de calzas fáciles disponibles si necesita admitir navegadores muy viejos también