Tengo problemas para entender la forma correcta de manejar las excepciones de las funciones asíncronas sin activar la advertencia de rechazo de promesa no controlada de UnhandledPromiseRejectionWarning (ya que eso parece sugerir que estoy haciendo algo mal).
Normalmente, en el código no asíncrono, las excepciones no controladas se propagan hasta la parte superior y finalmente se imprimen en la consola. El código que dio como resultado la excepción se detiene en toda la copia de seguridad de la pila.
Digamos que tengo el siguiente código:
test1().catch((e) => { throw e; }); console.log('got here top-level'); // This will print async function test1() { let test2Result = await test2(); console.log('got here test 1'); // This won't print return test2Result; } async function test2() { throw new Error('something failed here'); } Esperaría que esto hiciera lo que quiero. En el nivel más alto, detecta la excepción de las funciones asíncronas y las vuelve a lanzar (pero ahora fuera de cualquier código asíncrono o Promesas). Todavía debería tener el seguimiento de la pila original para que pueda encontrar el problema. Días felices, ¿verdad? Pero no, esto todavía resulta en UnhandledPromiseRejectionWarning y no entiendo por qué.
¿Cuál es la forma correcta de capturar todas las excepciones no controladas desde Promises?
Su malentendido proviene de esta declaración...
captura la excepción de las funciones asíncronas y las vuelve a lanzar (pero ahora fuera de cualquier código asíncrono o Promesas)
Promise.prototype.catch() sigue siendo un código asíncrono. Devuelve una Promesa, al igual que .then() (de hecho, .catch(onRejected) es simplemente un alias para .then(undefined, onRejected) ).
Dato curioso, si la devolución de llamada .catch() no devuelve una promesa rechazada (por ejemplo Promise.reject() ) o throw , devuelve una promesa exitosa/resuelta.
Cuando throw e dentro de su .catch() , el valor de retorno es una Promesa rechazada y dado que esto no se controla/no se captura, obtiene el infame UnhandledPromiseRejectionWarning .
Para evitarlo, simplemente maneje todos los posibles rechazos de promesas
test1().catch(console.error); // returns a resolved promise // or try { await test1(); } catch (e) { // consider this handled }Generalmente hago algo como esto:
async function main() { // do some async stuff here await someAsyncWork(); } let cc; main() .then( () => { console.log('success!'); cc = 0 ; } .catch( e => { console.error(e.stack); cc = 1; }) .finally( () => process.exit(cc) );