Espere hasta que se completen todas las promesas, incluso si algunas se rechazaron.

Resuelto Nathan Hagen asked hace 9 años • 20 respuestas

Digamos que tengo un conjunto de Promisemensajes 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.allno deja espacio para esto, ¿cuál es el patrón recomendado para manejar esto sin utilizar una biblioteca de promesas?

Nathan Hagen avatar Jul 15 '15 14:07 Nathan Hagen
Aceptado

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");
});
Benjamin Gruenbaum avatar Jul 15 '2015 08:07 Benjamin Gruenbaum

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>
Expandir fragmento

Dependiendo de los tipos de valores devueltos, los errores a menudo se pueden distinguir con bastante facilidad (por ejemplo, utilizarlos undefinedpara "no me importa", typeofpara valores simples que no son de objeto, result.messageetc. result.toString().startsWith("Error:"))

jib avatar Mar 20 '2016 15:03 jib