Come evitare jQuery promette completamente quando si concatenano due funzioni jQuery asincrone?

Ho visto molti tutorial sul nuovo EMCA che promettono di evitare le “promesse” nella libreria jQuery. Di solito dicono che puoi schivarli facendo qualcosa del genere:

Promise.resolve($.getJSON(url, params)); // voila! the jQuery promise is "gone"! 

Tuttavia, questo non funziona quando devo concatenare due funzioni asincrone di jQuery. Come collegherei due chiamate getJSON (dove la seconda chiamata dipende dal primo) insieme senza usare jQuery () o .when ()?

Invece, voglio solo usare Promise.all ecc.

Penso che un problema simile potrebbe essere l’interleaving delle promesse di jquery e EMCA?

Puoi adottare uno dei due approcci …

Converti quindi unisci:

 var p1 = Promise.resolve($.getJSON(url_1, params_1)); // voila 1! var p2 = Promise.resolve($.getJSON(url_2, params_2)); // voila 2! var p3 = Promise.all([p1, p2]).then(...); 

Combina quindi converti:

 var p1 = $.getJSON(url_1, params_1); var p2 = $.getJSON(url_2, params_2); var p3 = Promise.resolve($.when(p1, p2)).then(...); // voila 1 and 2! 

Semplicemente, entrambi gli approcci ti daranno una promise ES6 nativa, p3 , che si risolve quando entrambe le promesse jQuery si risolvono, o viene respinta quando una delle promesse fallisce.

Tuttavia, probabilmente siete interessati ai risultati delle due chiamate getJSON() , e jQuery è scomodo a questo proposito. jqXHR di jQuery promette di passare più parametri al loro successo e ai callback degli errori, mentre una promise ES6 ne accetta solo una; il resto sarà ignorato. Fortunatamente, è abbastanza semplice raggruppare insieme più parametri per creare un singolo object. Questo deve essere fatto in jQuery prima della conversione in ES6.

Il codice “converti quindi combina” si espande come segue:

 var p1 = Promise.resolve($.getJSON(url_1, params_1).then( function(data, textStatus, jqXHR) { return { data:data, textStatus:textStatus, jqXHR:jqXHR }; }, function(jqXHR, textStatus, errorThrown) { return { jqXHR:jqXHR, textStatus:textStatus, errorThrown:errorThrown }; } )); var p2 = Promise.resolve($.getJSON(url_2, params_2).then( function(data, textStatus, jqXHR) { return { data:data, textStatus:textStatus, jqXHR:jqXHR }; }, function(jqXHR, textStatus, errorThrown) { return { errorThrown:errorThrown, textStatus:textStatus, jqXHR:jqXHR }; } )); var p3 = Promise.all([p1, p2]).then( function(results) { // results[0] will be an object with properties .data, .textStatus, .jqXHR // results[1] will be an object with properties .data, .textStatus, .jqXHR }, function(rejectVal) { // rejectVal will be an object with properties .errorThrown, .textStatus, .jqXHR } ); 

L’approccio “combina poi converti” è leggermente più complicato in quanto i risultati combinati appaiono (in jQuery) come un elenco di arguments , che a sua volta deve essere convertito (sempre in jQuery) in una matrice.

 var p1 = $.getJSON(url_1, params_1).then( function(data, textStatus, jqXHR) { return { data:data, textStatus:textStatus, jqXHR:jqXHR }; }, function(jqXHR, textStatus, errorThrown) { return { errorThrown:errorThrown, textStatus:textStatus, jqXHR:jqXHR }; } ); var p2 = $.getJSON(url_2, params_2).then( function(data, textStatus, jqXHR) { return { data:data, textStatus:textStatus, jqXHR:jqXHR }; }, function(jqXHR, textStatus, errorThrown) { return { errorThrown:errorThrown, textStatus:textStatus, jqXHR:jqXHR }; } ); var p3 = Promise.resolve($.when(p1, p2).then(function() { return [].slice.call(arguments);// <<< convert arguments list to Array })).then( function(results) { // results[0] will be an object with properties .data, .textStatus, .jqXHR // results[1] will be an object with properties .data, .textStatus, .jqXHR }, function(rejectVal) { // rejectVal will be an object with properties .errorThrown, .textStatus, .jqXHR } ); 

DEMO: risolto

DEMO: respinto

Le promesse di JavaScript sono interoperabili . Puoi mescolarli come preferisci, tutte le librerie appropriate 1 e le promesse native accettano accettabili 2 da qualsiasi implementazione ovunque 3 . Se appare qualcosa di estraneo, lo faranno solo Promise.resolve su di esso.

Di solito scriverebbe il tuo codice come se tutti usassero la stessa implementazione promise, e funziona davvero .
Tuttavia, ora vuoi assicurarti che tutte le chiamate al metodo di questo tipo stiano usando la tua implementazione preferita; o vuoi usare un metodo o una funzione non standard? Per questo, dovrai lanciare esplicitamente tutte le promesse su cui stai invocando i metodi direttamente e nient’altro.

Qualche esempio:

 Promise.all([$.ajax(…), $.ajax(…)]).then(…); // just works! 
 $.ajax(…) // a jQuery promise .then(…) // so this would be jQuery `then`, which we don't want. 
 Promise.resolve($.ajax(…)) // explicit cast .then(function(data) { // native `then` return $.ajax(…); // just works! }) // returns a native promise still .catch(…) // so we can use its features 

1: Sì, jQuery non è uno di questi fino alla versione 3.0
2: tutti i differiti e le promesse di jQuery sono tali, quindi
3: In realtà ovunque ti aspetti una promise, in Promise.resolve , then valori di ritorno della callback, Promise.all argomenti Promise.all , …