Espere hasta que se completen todas las promesas, incluso si algunas se rechazaron.
Digamos que tengo un conjunto de Promise
mensajes de correo electrónico que realizan solicitudes de red, de los cuales uno fallará:
// http://does-not-exist will throw a TypeError
var arr = [ fetch('index.html'), fetch('http://does-not-exist') ]
Promise.all(arr)
.then(res => console.log('success', res))
.catch(err => console.log('error', err)) // This is executed
Digamos que quiero esperar hasta que todos hayan terminado, independientemente de si uno ha fallado. Puede haber un error de red para un recurso sin el que puedo vivir, pero que, si puedo obtenerlo, lo quiero antes de continuar. Quiero manejar las fallas de la red con elegancia.
Dado que Promise.all
no deja espacio para esto, ¿cuál es el patrón recomendado para manejar esto sin utilizar una biblioteca de promesas?
Actualización, probablemente quieras usar el nativo integrado Promise.allSettled
:
Promise.allSettled([promise]).then(([result]) => {
//reach here regardless
// {status: "fulfilled", value: 33}
});
Como dato curioso, esta respuesta a continuación fue la técnica anterior al agregar ese método al lenguaje :]
Claro, solo necesitas un reflect
:
const reflect = p => p.then(v => ({v, status: "fulfilled" }),
e => ({e, status: "rejected" }));
reflect(promise).then((v) => {
console.log(v.status);
});
O con ES5:
function reflect(promise){
return promise.then(function(v){ return {v:v, status: "fulfilled" }},
function(e){ return {e:e, status: "rejected" }});
}
reflect(promise).then(function(v){
console.log(v.status);
});
O en tu ejemplo:
var arr = [ fetch('index.html'), fetch('http://does-not-exist') ]
Promise.all(arr.map(reflect)).then(function(results){
var success = results.filter(x => x.status === "fulfilled");
});
Respuesta similar, pero quizás más idiomática para ES6:
const a = Promise.resolve(1);
const b = Promise.reject(new Error(2));
const c = Promise.resolve(3);
Promise.all([a, b, c].map(p => p.catch(e => e)))
.then(results => console.log(results)) // 1,Error: 2,3
.catch(e => console.log(e));
const console = { log: msg => div.innerHTML += msg + "<br>"};
<div id="div"></div>
Dependiendo de los tipos de valores devueltos, los errores a menudo se pueden distinguir con bastante facilidad (por ejemplo, utilizarlos undefined
para "no me importa", typeof
para valores simples que no son de objeto, result.message
etc. result.toString().startsWith("Error:")
)