Question

J'ai une application qui nécessite que les données soient chargées dans un certain ordre: l'URL racine, puis les schémas, puis enfin initialiser l'application avec les schémas et les URL des différents objets de données. Lorsque l'utilisateur navigue dans l'application, les objets de données sont chargés, validés par rapport au schéma et affichés. Lorsque l'utilisateur CRUDs les données, les schémas fournissent une validation de premier passage.

J'ai un problème avec l'initialisation. J'utilise un appel Ajax pour récupérer l'objet racine, $ .when (), puis je crée un tableau de promesses, une pour chaque objet de schéma. Ça marche. Je vois la récupération dans la console.

Je vois ensuite la récupération de tous les schémas, donc chaque appel $ .ajax () fonctionne. fetchschemas () renvoie en effet un tableau de promesses.

Cependant, cette dernière clause when () ne se déclenche jamais et le mot "DONE" n'apparaît jamais sur la console. Le code source de jquery-1.5 semble impliquer que "null" est acceptable comme objet à passer à $ .when.apply (), comme when () construira un objet Deferred () interne pour gérer la liste si aucun objet n'est transmis.

Cela a fonctionné avec Futures.js. Comment gérer un tableau de jQuery Deferred, sinon comme ça?

    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);
        });
    });
Était-ce utile?

La solution

Vous recherchez

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

Cela fonctionnera également (pour une certaine valeur de travail, cela ne corrigera pas un ajax cassé):

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

Vous voudrez passer $ au lieu de null afin que this dans $.when se réfère à jQuery.Cela ne devrait pas avoir d'importance pour la source, mais c'est mieux que de passer null.

J'ai simulé tous vos $ .ajax en les remplaçant par $.when et l'exemple de fonctionne

C'est donc soit un problème dans votre requête ajax, soit dans le tableau que vous passez à fetch_schemas.

Autres conseils

La solution de contournement ci-dessus (merci!) ne résout pas correctement le problème de la récupération des objets fournis à la méthode resolve() du différé car jQuery appelle les rappels done() et fail() avec des paramètres individuels, pas un tableau.Cela signifie que nous devons utiliser le pseudo-tableau arguments pour obtenir tous les objets résolus / rejetés retournés par le tableau de différés, ce qui est moche:

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

Puisque nous avons passé un tableau de différés, ce serait bien de récupérer un tableau de résultats.Ce serait également bien de récupérer un tableau réel au lieu d'un pseudo-tableau afin que nous puissions utiliser des méthodes comme Array.sort().

Voici une solution inspirée de la méthode when.all() de when.js qui résout ces problèmes:

// 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;
    }
}

Maintenant, vous pouvez simplement passer un tableau de différés / promesses et récupérer un tableau d'objets résolus / rejetés dans votre rappel, comme ceci:

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

Si vous utilisez la version ES6 de javascript Il existe un opérateur de propagation (...) qui convertit un tableau d'objets en arguments séparés par des virgules.

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

En savoir plus sur l'opérateur de diffusion ES6 https://developer.mozilla.org/fr-FR / docs / Web / JavaScript / Reference / Operators / Spread_operator trouver ici

se prolonge avec ce code:

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)
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top