Come lavori con una serie di jQuery differiti?
-
28-10-2019 - |
Domanda
Ho un'applicazione che richiede che i dati vengano caricati in un determinato ordine: l'URL root, quindi gli schemi, quindi infine inizializza l'applicazione con gli schemi e gli URL per i vari oggetti dati. Man mano che l'utente naviga nell'applicazione, gli oggetti dati vengono caricati, validati rispetto allo schema e visualizzati. Man mano che l'utente gregge i dati, gli schemi forniscono la convalida del primo passaggio.
Ho un problema con l'inizializzazione. Uso una chiamata AJAX per recuperare l'oggetto root, $ .When (), quindi creare una serie di promesse, una per ogni oggetto schema. Che funzioni. Vedo il recupero nella console.
Quindi vedo il recupero per tutti gli schemi, quindi ogni $ .ajax () si chiama. fetchschemas () restituisce effettivamente una serie di promesse.
Tuttavia, quella clausola finale quando () non si accende mai e la parola "fatta" non appare mai sulla console. Il codice sorgente su jQuery-1.5 sembra implicare che "null" sia accettabile come oggetto per passare a $ .When.apply (), come quando () costruirà un oggetto Defered () interno per gestire l'elenco se nessun oggetto è Passato.
Questo ha funzionato usando Futures.js. Come dovrebbe essere gestita una serie di jQuery differiti, se non così?
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);
});
});
Soluzione
Stai cercando
$.when.apply($, promises).then(function(schemas) {
console.log("DONE", this, schemas);
}, function(e) {
console.log("My ajax failed");
});
Funzionerà anche (per un certo valore di lavoro, non risolverà l'Ajax rotto):
$.when.apply($, promises).done(function() { ... }).fail(function() { ... });`
Ti consigliamo di passare $
invece di null
affinché this
dentro $.when
si riferisce a jQuery
. Non dovrebbe importare per la fonte, ma è meglio di passare null
.
Deriditi tutti i tuoi $ .ajax sostituendoli $.when
e il campione lavori
Quindi è un problema nella tua richiesta Ajax o nell'array la tua scomparsa a fetch_schemas.
Altri suggerimenti
La soluzione alternativa sopra (grazie!) Non affronta correttamente il problema di recuperare gli oggetti forniti ai differiti resolve()
metodo perché jQuery chiama il done()
e fail()
callback con singoli parametri, non un array. Ciò significa che dobbiamo usare il arguments
pseudo-array per ottenere tutti gli oggetti risolti/rifiutati restituiti dalla matrice di differiti, che è brutto:
$.when.apply($, promises).then(function() {
var schemas=arguments; // The array of resolved objects as a pseudo-array
...
};
Da quando siamo passati in una serie di differiti, sarebbe bello recuperare una serie di risultati. Sarebbe anche bello recuperare un vero array anziché uno pseudo-array in modo da poter usare metodi come Array.sort()
.
Ecco una soluzione ispirata da quando.js'S when.all()
Metodo che affronta questi problemi:
// 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;
}
}
Ora puoi semplicemente passare in una serie di differiti/promesse e riprendere una serie di oggetti risolti/rifiutati nel callback, in questo modo:
$.when.all(promises).then(function(schemas) {
console.log("DONE", this, schemas); // 'schemas' is now an array
}, function(e) {
console.log("My ajax failed");
});
Se si utilizza la versione ES6 di JavaScript, esiste un operatore di diffusione (...) che converte l'array di oggetti in argomenti separati da virgola.
$.when(...promises).then(function() {
var schemas=arguments;
};
Maggiori informazioni sull'operatore di spread ES6 https://developer.mozilla.org/en-us/docs/web/javascript/reference/operator/spread_operator Trova qui
si estende quando con questo codice:
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)
}
}