¿Cómo puedo rechazar una promesa devuelta por una función asíncrona / espera?
por ejemplo, originalmente
foo(id: string): Promise<A> {
return new Promise((resolve, reject) => {
someAsyncPromise().then((value)=>resolve(200)).catch((err)=>reject(400))
});
}
Traducir a asíncrono / esperar
async foo(id: string): Promise<A> {
try{
await someAsyncPromise();
return 200;
} catch(error) {//here goes if someAsyncPromise() rejected}
return 400; //this will result in a resolved promise.
});
}
Entonces, ¿cómo podría rechazar adecuadamente esta promesa en este caso?
Promise
constructor antipatrón ! Incluso el primer fragmento debería haberse escritofoo(id: string): Promise<A> { return someAsyncPromise().then(()=>{ return 200; }, ()=>{ throw 400; }); }
Respuestas:
Su mejor apuesta es
throw
unaError
envoltura del valor, lo que resulta en una promesa rechazada con unaError
envoltura del valor:También puede solo
throw
el valor, pero no hay información de seguimiento de la pila:Alternativamente, devuelva una promesa rechazada con una
Error
envoltura del valor, pero no es idiomático:(O simplemente
return Promise.reject(400);
, pero de nuevo, entonces no hay información de contexto).(En su caso, como está usando
TypeScript
yfoo
el valor de recuperación esPromise<A>
, usaríareturn Promise.reject<A>(400 /*or error*/);
)En una situación
async
/await
, ese último es probablemente un poco de coincidencia semántica, pero funciona.Si arroja un
Error
, eso juega bien con cualquier cosa que consuma elfoo
resultado de suawait
sintaxis:fuente
throw
es mejor quePromise.reject()
IMO. Sithrow 400
es una pregunta diferente. En el OP está rechazando 400, y podemos argumentar que debería rechazar unError
en su lugar.async
funciones, no hayresolve
oreject
función. Hayreturn
ythrow
, cuáles son las formas idiomáticas de resolver y rechazar laasync
promesa de la función.new
hace explícito. También tenga en cuenta que no puede dejarlo fuera si tiene unaError
subclase (class MyError extends Error
), así que ...Probablemente también debería mencionarse que simplemente puede encadenar una
catch()
función después de la llamada de su operación asincrónica porque, bajo el capó, aún se devuelve una promesa.De esta forma, puede evitar la
try/catch
sintaxis si no le gusta.fuente
async
función, lanzo una excepción y luego la atrapo muy bien,.catch()
como si volvieraPromise.reject
o llamarareject
. ¡Me gusta!await
fallas posibles en una rutina. A menos que se necesiten casos muy específicos para cada unoawait
, no veo por qué querría atraparlos así. Solo yo humilde opinión.await
falla por separado, sino que también necesitaba trabajar con un marco basado en Promise que rechazara las promesas por error.${host}/user/permissions/repositories_wrong_url/
, accessToken, accessTokenSecret) .catch (err => {logger.error ('No se pueden recuperar los permisos del repositorio', err); devolución de llamada (err);})await
palabra clave aquí.Puede crear una función de contenedor que promete y devuelve una matriz con datos si no hay error y el error si hubo un error.
Úselo así en ES7 y en una función asíncrona :
fuente
Una mejor manera de escribir la función asíncrona sería devolviendo una Promesa pendiente desde el principio y luego manejando tanto los rechazos como las resoluciones dentro de la devolución de llamada de la promesa, en lugar de escupir una promesa rechazada por error. Ejemplo:
Luego, solo encadena métodos en la promesa devuelta:
Fuente: este tutorial:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
fuente
Tengo una sugerencia para manejar adecuadamente los rechazos en un enfoque novedoso, sin tener múltiples bloques try-catch.
Donde se debe importar la función to.ts desde:
Los créditos van a Dima Grossman en el siguiente enlace .
fuente
let [err]=
si solo busca errores.Esta no es una respuesta sobre la de @TJ Crowder. Solo un comentario que responde al comentario "Y, de hecho, si la excepción se convertirá en un rechazo, no estoy seguro de si realmente me molesta si se trata de un error. Mis razones para arrojar solo el error probablemente no se apliquen. "
si su código está usando
async
/await
, entonces es una buena práctica rechazar con un enError
lugar de400
:fuente
Sé que esta es una vieja pregunta, pero acabo de tropezar con el hilo y parece haber una confusión entre errores y rechazo que entra en conflicto (al menos en muchos casos) con los consejos que se repiten a menudo para no usar el manejo de excepciones para lidiar con casos anticipados. Para ilustrar: si un método asincrónico está intentando autenticar a un usuario y la autenticación falla, es un rechazo (uno de los dos casos previstos) y no un error (por ejemplo, si la API de autenticación no estaba disponible).
Para asegurarme de que no solo estaba dividiendo pelos, realicé una prueba de rendimiento de tres enfoques diferentes para eso, usando este código:
Algunas de las cosas que están allí están incluidas debido a mi incertidumbre con respecto al intérprete de Javascript (solo me gusta ir por una madriguera a la vez); por ejemplo, incluí la
doSomething
función y asigné su retorno adummyValue
para garantizar que los bloques condicionales no se optimizaran.Mis resultados fueron:
Sé que hay muchos casos en los que no vale la pena buscar pequeñas optimizaciones, pero en sistemas a gran escala, estas cosas pueden hacer una gran diferencia acumulativa, y esa es una comparación bastante dura.
ASÍ… aunque creo que el enfoque de la respuesta aceptada es sólido en los casos en que espera tener que manejar errores impredecibles dentro de una función asincrónica, en los casos en que un rechazo simplemente significa "tendrá que seguir el Plan B (o C o D ...) "Creo que mi preferencia sería rechazar el uso de un objeto de respuesta personalizado.
fuente