Pregunta

Tengo una aplicación que requiere que los datos se carguen en cierto orden: la URL raíz, luego los esquemas, luego 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 ensucia los datos, los esquemas proporcionan 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 la búsqueda en la consola.

Luego veo la búsqueda de todos los esquemas, por lo que cada llamada $ .AJAX () funciona. FetchSchemas () de hecho devuelve una variedad de promesas.

Sin embargo, esa cláusula final cuando () nunca dispara y la palabra "hecho" nunca aparece en la consola. El código fuente a jQuery-1.5 parece implicar que "nulo" es aceptable como un objeto para pasar a $ .When.apply (), como cuando () construirá un objeto interno diferido () para administrar la lista si no es objeto es aprobada en.

Esto funcionó usando futures.js. ¿Cómo se debe gestionar una serie de jQuery Diferreds, si no 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);
        });
    });
¿Fue útil?

Solución

Estas buscando

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

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

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

Querrás pasar $ en vez de null de modo que this en el interior $.when se refiere a jQuery. No debería importar a la fuente, pero es mejor que pasar null.

Se burló de todos sus $ .AJAX reemplazándolos con $.when y la muestra obras

Por lo tanto, es un problema en su solicitud AJAX o en la matriz su pase a Fetch_schemas.

Otros consejos

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

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

Desde que pasamos en una variedad de diferidos, sería bueno recuperar una variedad 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 cuando.js's when.all() Método que aborde 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 variedad de diferencias/promesas y recuperar una variedad de objetos resueltos/rechazados en su devolución de llamada, como 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 spread (...) que convierte la matriz de objetos en argumentos separados por comas.

$.when(...promises).then(function() {
 var schemas=arguments; 
};

Más sobre el operador de propagación de ES6 https://developer.mozilla.org/en-us/docs/web/javascript/reference/operators/spead_operator encontrar aquí

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)
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top