tag section name attribute jquery jquery-deferred .when

section - ¿Cómo trabajas con una variedad de jQuery diferidos?



select name jquery (4)

Tengo una aplicación que requiere que los datos se carguen en un orden determinado: la URL raíz, luego los esquemas, y finalmente inicializan la aplicación con los esquemas y las URL para los diversos objetos de datos. A medida que el usuario navega por la aplicación, los objetos de datos se cargan, validan contra el esquema y se muestran. A medida que el usuario CRUDE los datos, los esquemas brindan validación de primer paso.

Estoy teniendo un problema con la inicialización. Uso una llamada Ajax para buscar el objeto raíz, $ .when (), y luego creo una matriz de promesas, una para cada objeto de esquema. Eso funciona. Veo la búsqueda en la consola.

Luego veo la búsqueda de todos los esquemas, por lo que cada llamada a $ .ajax () funciona. fetchschemas () realmente devuelve una serie de promesas.

Sin embargo, esa cláusula final cuando () nunca se dispara y la palabra "HECHO" nunca aparece en la consola. El código fuente de jquery-1.5 parece implicar que "nulo" es aceptable como un objeto para pasar a $ .when.apply (), como cuando () construirá un objeto interno Deferred () para administrar la lista si no hay ningún objeto aprobada en.

Esto funcionó usando Futures.js. ¿Cómo se debe gestionar una matriz de jQuery Deferreds, si no es así?

var fetch_schemas, fetch_root; fetch_schemas = function(schema_urls) { var fetch_one = function(url) { return $.ajax({ url: url, data: {}, contentType: "application/json; charset=utf-8", dataType: "json" }); }; return $.map(schema_urls, fetch_one); }; fetch_root = function() { return $.ajax({ url: BASE_URL, data: {}, contentType: "application/json; charset=utf-8", dataType: "json" }); }; $.when(fetch_root()).then(function(data) { var promises = fetch_schemas(data.schema_urls); $.when.apply(null, promises).then(function(schemas) { console.log("DONE", this, schemas); }); });


Estas buscando

$.when.apply($, promises).then(function(schemas) { console.log("DONE", this, schemas); }, function(e) { console.log("My ajax failed"); });

Esto también funcionará (por algún valor de trabajo, no arreglará ajax roto):

$.when.apply($, promises).done(function() { ... }).fail(function() { ... });`

Querrá pasar $ lugar de null para que this dentro de $.when refiera a jQuery . No debería importar a la fuente, pero es mejor pasar el null .

Se burló de todos tus $ .ajax reemplazándolos con $.when y la muestra works

Por lo tanto, es un problema en su solicitud de Ajax o la matriz que pasa a fetch_schemas.


La solución anterior (¡gracias!) No aborda correctamente el problema de recuperar los objetos proporcionados al método de resolve() diferida resolve() porque jQuery llama a las devoluciones de llamada done() y fail() con parámetros individuales, no una matriz. Eso significa que tenemos que usar los arguments pseudo-array para obtener todos los objetos resueltos / rechazados devueltos por la matriz de diferidos, lo cual es feo:

$.when.apply($, promises).then(function() { var schemas=arguments; // The array of resolved objects as a pseudo-array ... };

Ya que pasamos en una serie de diferidos, sería bueno obtener una serie de resultados. También sería bueno recuperar una matriz real en lugar de una pseudo-matriz para que podamos usar métodos como Array.sort() .

Aquí hay una solución inspirada por el método when.all() que resuelve estos problemas:

// Put somewhere in your scripting environment if (jQuery.when.all===undefined) { jQuery.when.all = function(deferreds) { var deferred = new jQuery.Deferred(); $.when.apply(jQuery, deferreds).then( function() { deferred.resolve(Array.prototype.slice.call(arguments)); }, function() { deferred.fail(Array.prototype.slice.call(arguments)); }); return deferred; } }

Ahora puede simplemente pasar una serie de diferidos / promesas y recuperar una serie de objetos resueltos / rechazados en su devolución de llamada, así:

$.when.all(promises).then(function(schemas) { console.log("DONE", this, schemas); // ''schemas'' is now an array }, function(e) { console.log("My ajax failed"); });



se extiende cuando con este código:

var rawWhen = $.when $.when = function(promise) { if ($.isArray(promise)) { var dfd = new jQuery.Deferred() rawWhen.apply($, promise).done(function() { dfd.resolve(Array.prototype.slice.call(arguments)) }).fail(function() { dfd.reject(Array.prototype.slice.call(arguments)) }) return dfd.promise() } else { return rawWhen.apply($, arguments) } }