Tengo una aplicación que requiere que los datos se carguen en un cierto orden: la URL raíz, luego los esquemas y, finalmente, inicializar 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, se validan con el esquema y se muestran. A medida que el usuario aplica CRUD a los datos, los esquemas proporcionan una validación de primer paso.
Tengo un problema con la inicialización. Utilizo una llamada Ajax para obtener el objeto raíz, $.when(), y luego creo una matriz de promesas, una para cada objeto de esquema. Eso funciona. Veo el fetch en la consola.
Luego veo la búsqueda de todos los esquemas, por lo que cada llamada $.ajax() funciona. fetchschemas() de hecho devuelve una serie de promesas.
Sin embargo, esa cláusula final when() nunca se activa y la palabra "DONE" nunca aparece en la consola. El código fuente de jquery-1.5 parece implicar que "null" es aceptable como un objeto para pasar a $.when.apply(), ya que when() creará un objeto Deferred() interno para administrar la lista si no hay ningún objeto. aprobada en.
Esto funcionó usando Futures.js. ¿Cómo se debe administrar 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 $ en lugar de null para que this dentro $.when se refiera a jQuery . No debería importarle a la fuente, pero es mejor que pasar null .
Se burló de todos sus $.ajax reemplazándolos con $.when y la muestra funciona
Entonces, es un problema en su solicitud ajax o en la matriz que está pasando a fetch_schemas.
La solución anterior (¡gracias!) no aborda correctamente el problema de recuperar los objetos proporcionados al método resolve() del diferido porque jQuery llama a las devoluciones de llamada done() y fail() con parámetros individuales, no una matriz. Eso significa que tenemos que usar la pseudo matriz de arguments 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 ... }; Dado que pasamos 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 en el método when.all when.all() de when.js que aborda 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"); });Si está utilizando la versión ES6 de javascript, hay un operador de propagación (...) que convierte una matriz de objetos en argumentos separados por comas.
$.when(...promises).then(function() { var schemas=arguments; };Más información sobre el operador de propagación ES6 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator encontrar aquí