¿Por qué el siguiente código informa un error Uncaught (in promise) rejected cuando se detecta?
function Test() { this.start = function(action) { return new Promise((resolve, reject) => { setTimeout(() => { if (action == "fail") return reject("rejected"); resolve("resolved"); }, 1000); }); } } const test = new Test(); const promise = test.start("fail"); promise.then(console.log); promise.catch(console.error);La salida (en un navegador) es:
rejected de la captura ()
Uncaught (in promise) rejected de la llamada a rechazar
Estás bifurcando tu cadena de promesas:
promise ---> .then( .. ) ---> ??? \ \ +-> .catch( .. ) El rechazo está siendo capturado por .catch muy bien, pero también pasa por la rama .then . Ambas ramas se resuelven de forma independiente. Y no está detectando el rechazo en la rama .then , lo que lleva al error de rechazo no detectado.
Comparar con:
promise.then(console.log).catch(console.error)Aquí la cadena se ve así:
promise ---> .then( .. ) ---> .catch( .. ) El rechazo omitirá el controlador .then e irá al .catch más cercano.
Está bien. La respuesta es obvia, pero fácil de pasar por alto.
.then(...) devuelve otra promesa. Así que tienes que adjuntar el .catch(...) a ESO.
Solución:
const promise = test.start("fail"); promise.then(console.log).catch(console.error);O más explícitamente:
const promise = test.start("fail"); const promise2 = promise.then(console.log); promise2.catch(console.error); La respuesta/explicación de @deceze es bastante buena.
Aquí está el código corregido:
function Test() { this.start = function(action) { return new Promise((resolve, reject) => { setTimeout(() => { if (action == "fail") return reject(new Error("rejected")); resolve("resolved"); }, 1000); }); } } const test = new Test(); const promise = test.start("fail"); promise.then(console.log).catch(console.error);necesita encadenar .then() y .catch() para que funcione,
porque .then() devolverá una nueva promesa, y es esa promesa la que arrojará el error que debe detectar