Estoy haciendo varias llamadas a la API, después de lo cual quiero cargar los resultados combinados de cada llamada:
$.when( $.get(localAPI, data, function(response) { globalStore.localShares = Number(response); }), $.get(facebookAPI, '', function(response){ globalStore.facebookShares = Number(response[0].share_count); }), $.getJSON(pinterestAPI, {url: url}).done(function(response){ globalStore.pinterestShares = Number(response.count); }) ).always(function(){ //Do stuff }); Si las llamadas $.get fallan, la función de devolución de llamada $.always todavía se ejecuta.
Pero
Si solo falla una llamada $.get , niega las acciones de las llamadas anteriores.
Entonces, si falla la primera llamada, globalStore regresa con dos artículos. Si la primera llamada tiene éxito pero la segunda falla, globalStore regresa con solo un elemento. Y si las dos primeras llamadas tienen éxito pero la última falla, globalStore regresa vacío.
¿Hay alguna forma de evitar esto?
Editar:
Sí, he tratado de manejar fallas dentro $.when así:
$.when( $.get(mu30_ajax_frontend.ajaxurl, data, function(response) { globalStore.localShares = Number(response); }).fail(function(){ globalStore.localShares = 0; }), $.get(facebookAPI, '', function(response){ globalStore.facebookShares = Number(response[0].share_count); }).fail(function(){ globalStore.facebookShares = 0; }), $.getJSON(pinterestAPI, {url: url}).done(function(response){ globalStore.pinterestShares = Number(response.count); }).fail(function(){ globalStore.pinterestShares = 0; }) ).always(function(){ //Do stuff });Pero obtengo el mismo resultado.
No hay forma de evitar esto cuando se usa $.when Cuando de esa manera, si falla una solicitud, falla toda la cadena.
En su lugar, tendría que hacer el suyo propio, usando diferidos para saber cuándo se completaron todas las llamadas, y siempre resolviendo con éxito, etc.
var defs = [new $.Deferred(), new $.Deferred(), new $.Deferred()]; $.get(localAPI, data, function(response) { globalStore.localShares = Number(response); defs[0].resolve(true); }).fail(defs[0].resolve); $.get(facebookAPI, '', function(response){ globalStore.facebookShares = Number(response[0].share_count); defs[1].resolve(true); }).fail(defs[1].resolve); $.getJSON(pinterestAPI, {url: url}).done(function(response){ globalStore.pinterestShares = Number(response.count); defs[2].resolve(true); }).fail(defs[2].resolve); $.when.apply($, defs).then(function(result) { // result is an array, any true value is a successful request "[true, true, true]" });escrito detalladamente, esto podría ser embellecido con algunas funciones y bucles, etc.
Creo que la solución que necesitaba era en realidad simple. No me importaba el éxito o el fracaso, solo quería saber cuándo terminaba Ajax. Asi que:
$.get(mu30_ajax_frontend.ajaxurl, data, function(response) { globalStore.localShares = Number(response); }); $.get(facebookAPI, '', function(response){ globalStore.facebookShares = Number(response[0].share_count); }); $.getJSON(pinterestAPI, {url: url}).done(function(response){ globalStore.pinterestShares = Number(response.count); }); $(document).ajaxStop(function(){ //Do stuff });De los documentos de jQuery $.when() (énfasis mío):
En el caso de que se pasen varios objetos diferidos a jQuery.when(), el método devuelve la promesa de un nuevo objeto diferido "maestro" que realiza un seguimiento del estado agregado de todos los diferidos que se han pasado. El método resolverá su diferido maestro tan pronto como se resuelvan todos los diferidos, o rechazará el diferido maestro tan pronto como se rechace uno de los diferidos .
Entonces, sí, jQuery.when fallará inmediatamente si una de las promesas pasadas es rechazada/falla.