Promise.all se rechaza si se rechaza alguno de los elementos . Por ejemplo, si pasa cuatro promesas que se resuelven después de un tiempo de espera y una promesa que se rechaza de inmediato, entonces Promise.all se rechazará de inmediato.
Analicemos el siguiente fragmento de código:
(async () => { try { const awaited = await Promise.all([ (() => { console.log('1'); return Promise.reject('2'); })(), (() => { console.log('3'); return Promise.resolve('4'); })(), ]); console.log(awaited); } catch (error) { console.log(error); } finally { console.log('5'); } })();Todas las promesas en el código anterior se resuelven/rechazan inmediatamente. Creo que el código debería ejecutarse de esta manera:
En cambio, veo que también se registra un '3'. ¿Por que es esto entonces?
En cambio, veo que también se registra un '3'. ¿Por que es esto entonces?
Todas las demás respuestas intentan explicar cómo funcionan las promesas o el ciclo de eventos, pero de hecho no tiene nada que ver con eso.
El argumento que pasa a Promise.all es una matriz que contiene los resultados de dos llamadas a funciones. Por lo tanto, se llamará a ambas funciones antes de llamar a Promise.all . Ambas funciones console.log un valor y luego devuelven una promesa. Promise.all recibe una matriz que contiene esas promesas. Entonces, antes de que Promise.all haga algo, ambas funciones ya se ejecutaron y registraron 1 y 3 respectivamente.
Tal vez sea más fácil verlo reestructurar su código para crear las promesas de antemano:
(async () => { try { const promise1 = (() => { console.log('1'); return Promise.reject('2'); })(); const promise2 = (() => { console.log('3'); return Promise.resolve('4'); })() const awaited = await Promise.all([promise1, promise2]); console.log(awaited); } catch (error) { console.log(error); } finally { console.log('5'); } })();Al igual que con cualquier otra función, todos los argumentos de la función se evalúan antes de llamar a la función en sí. El orden de los acontecimientos es más bien este:
2 .4 .Aquí hay un ejemplo más simple: tenga en cuenta que no se "hace" nada con el segundo argumento pasado a la función y, sin embargo, el valor aún se registra, precisamente porque todos los argumentos se evalúan primero:
function process(arg) { return 'Received ' + arg; } const result = process( (() => { console.log('1'); return 1; })(), (() => { console.log('3'); return 2; })(), ); console.log(result)Esto se debe a la forma en que se manejan las Promesas en JavaScript. Es de naturaleza asíncrona y no hay seguridad en cuanto al orden de ejecución. Tenga en cuenta que esto no es un error, sino una característica del lenguaje.
Le sugiero que lea más sobre el tema en esta pregunta SO y sobre el bucle de eventos .
Promise.all() falla rápidamente. Sin embargo, no aborta las otras Promesas de los acabados. Este ejemplo con tiempos de espera lo ilustra un poco mejor.
Promise.all([ Promise.reject(), new Promise((resolve, reject) => setTimeout(() => { console.log('a'); resolve(); }, 500)), new Promise((resolve, reject) => setTimeout(() => { console.log('b'); resolve(); }, 2000)) ]) .then(() => console.log('done')) .catch(() => console.log('fail')); Puede ver que Promise.all() llama a catch() casi de inmediato y deja de esperar los resultados del otro, porque no cambiará el resultado. Sin embargo, las otras dos Promesas no se abortan de ninguna manera.
Si desea abortarlos, tendría que implementar su propia lógica para hacerlo.