Estoy tratando de escribir una promesa de Javascript que resuelva y rechace las variables deseadas. Recibo el siguiente mensaje de error después de ejecutar en la consola
[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). code: 'ERR_UNHANDLED_REJECTION'Aquí está mi código
Archivo Js:
const grimeUserLeft = false; const userWatchingGrimeVids = true; let grimePromise = new Promise((resolve, reject) => { if (grimeUserLeft) { reject("User Left"); } else if (userWatchingGrimeVids) { reject("This user is a G"); } else { resolve("Congrats. Your channel doesn't suck"); } }); grimePromise.then((message) => { console.log("Success: " + message); }); grimePromise.catch((message) => { console.log("You Failed: " + message); });Al llamar al .then() y .catch() en dos lugares diferentes, en realidad termina con dos promesas diferentes: cada una de .then() y .catch() devuelve una nueva. La promesa devuelta por .then() no será capturada por el controlador .catch() separado:
const grimeUserLeft = false; const userWatchingGrimeVids = true; let grimePromise = new Promise((resolve, reject) => { if (grimeUserLeft) { reject("User Left"); } else if (userWatchingGrimeVids) { reject("This user is a G"); } else { resolve("Congrats. Your channel doesn't suck"); } }); grimePromise .then((message) => { console.log("Success: " + message); }) .catch(() => console.log(1)); grimePromise.catch((message) => { console.log(2); console.log("You Failed: " + message); });Por lo tanto, una promesa se convierte en dos. Cada uno de ellos adoptará el estado de la promesa original. Cuando se rechaza el original, se rechazan ambas promesas derivadas. Sin embargo, solo se maneja uno.
En su lugar, puede especificar directamente .catch() en la misma cadena de promesa que .then() :
const grimeUserLeft = false; const userWatchingGrimeVids = true; let grimePromise = new Promise((resolve, reject) => { if (grimeUserLeft) { reject("User Left"); } else if (userWatchingGrimeVids) { reject("This user is a G"); } else { resolve("Congrats. Your channel doesn't suck"); } }); grimePromise .then((message) => { console.log("Success: " + message); }) .catch((message) => { console.log("You Failed: " + message); }); <h1>Check the browser console - no unhandled promise rejections</h1> O alternativamente, especifique ambos controladores en el then() :
const grimeUserLeft = false; const userWatchingGrimeVids = true; let grimePromise = new Promise((resolve, reject) => { if (grimeUserLeft) { reject("User Left"); } else if (userWatchingGrimeVids) { reject("This user is a G"); } else { resolve("Congrats. Your channel doesn't suck"); } }); grimePromise .then( (message) => { console.log("Success: " + message); }, (message) => { console.log("You Failed: " + message); } ); <h1>Check the browser console - no unhandled promise rejections</h1>La razón por la que esto no funciona es porque no tenía un .catch() en el primero. Estaba lanzando un rechazo, pero no lo estabas manejando con gracia con una atrapada, por lo que lanzó.
Aquí está su código funcionando: acabo de mover su bloque catch para ir después de .then:
const grimeUserLeft = false; const userWatchingGrimeVids = true; const grimePromise = new Promise((resolve, reject) => { if (grimeUserLeft) { reject('User Left'); } else if (userWatchingGrimeVids) { reject('This user is a G'); } else { resolve("Congrats. Your channel doesn't suck"); } }); grimePromise .then((message) => { console.log('Success: ' + message); }) .catch((message) => { console.log('You Failed: ' + message); });Sin embargo, solo como un consejo, solo debe rechazar cuando la función no tenga éxito de alguna manera. Eso podría ser un tiempo de espera, un error de red, una entrada incorrecta, etc. Lo que sea que esté dentro de un rechazo idealmente debería ser un error.
Además, recomendaría usar async await, ya que es mucho más fácil de leer y más manejable. Puede hacer esto fácilmente creando una función que devuelva su nueva Promesa, y luego esperándola así:
const grimeUserLeft = false; const userWatchingGrimeVids = true; const grime = () => { return new Promise((resolve, reject) => { if (grimeUserLeft) { reject(new Error('User Left')); } else if (userWatchingGrimeVids) { resolve('This user is a G'); } else { resolve("Congrats. Your channel doesn't suck"); } }); }; const doStuff = async () => { try { const result = await grime(); console.log(result); } catch (error) { console.error(error); } }; doStuff();Para que esto sea verdaderamente asincrónico, idealmente deberías estar haciendo algunas cosas asíncronas dentro de la promesa. Esto se puede demostrar con un setTimeout:
const grimeUserLeft = false; const userWatchingGrimeVids = true; const grime = () => { return new Promise((resolve, reject) => { setTimeout(() => { if (grimeUserLeft) { reject(new Error('User Left')); } else if (userWatchingGrimeVids) { resolve('This user is a G'); } else { resolve("Congrats. Your channel doesn't suck"); } }, 2000); }); }; const doStuff = async () => { try { const result = await grime(); console.log('result finished after 2 seconds'); console.log(result); } catch (error) { console.error(error); } }; doStuff();