Hace unas horas estaba leyendo este post donde una persona explica como poder cambiar de cadenas de promesas a un mundo síncrono con async/await. Sin emgargo, el problema con async/await es la necesidad de usar try/catch para poder tener un fallback de cuando una promesa truena.
Efectivamente cambias esto:
const myFn = () => {
myPromise
.then(response => {
console.log('here')
})
.catch(error => {
console.log('error here')
})
}
a
const myFn = async () => {
let response
try {
response = await myPromise
} catch (error) {
response = error
}
}
Básicamente no hay mejora, pues el código sigue siendo igual de complicado de leer, además si no manejas el catch de la promesa rota, el intérprete te va a regresar una excepción.
Entonces en el post, @avishkardalvi nos explica una forma de poder escapar del async/await hell concentrando varias respuestas de estas promesas en un solo lugar y posteriormente regresando una tupla [error, respuesta]
.
Siento que es una buena forma de darle la vuelta a este problema, pero le faltó un poquito para que fuera redonda.
Entonces ESTE es mi approach para el mismo problema, basado en la propuesta original.
const aP = async promise => {
let res, err
try {
res = await promise
} catch (e) {
err = e
}
return [err, res]
}
const algo = async _ => {
const p = new Promise(resolve => resolve('success'))
const s = await aP(p)
const p2 = new Promise((_, reject) => reject('error'))
const s2 = await aP(p2)
console.log(s, s2)
}
algo()
Esto nos va a contestar en cada respuesta de aP
una tupla con el formato [error, response]
y eliminando todas las necesidades de tener que meter try/catch en cada una de las promesas y al mismo tiempo conservando la legibilidad del código resultante.
Esto se compone de dos partes:
Parte 1
El helper
const aP = async promise => {
let res, err
try {
res = await promise
} catch (e) {
err = e
}
return [err, res]
}
aP (corto para async promise) es una función que recibe una promesa tal cual, define los dos posibles resultados, intenta ejecutar la promesa y aqui está el único try/catch necesario, observemos que aP es una función async, es decir que incluso la función misma regresa una promesa que se pude encolar con otras promesas.
Parte 2
La implementación
const algo = async _ => {
const p = new Promise(resolve => resolve('success'))
const s = await aP(p)
const p2 = new Promise((_, reject) => reject('error'))
const s2 = await aP(p2)
console.log(s, s2)
}
algo()
Aquí simplemente definimos una función async donde tenermos dos ejemplos de promesas p
y p2
, donde p
contesta con un resolve (ejemplo todo cool) y p2
contesta con un reject (ejemplo de una promesa rota)
Ambas promesas las pasamos por el aP
quien intenta resolverlas y regresarnos una respuesta. El resultado es el siguiente:
Promise { <pending> }
[ undefined, 'success' ] [ 'error', undefined ]
Como pueden ver, en ambos casos, la tupla se genera corréctamente y no hay ningún warning acerca de que hubo un reject sin catch que rompiera la promesa.
¿Qué piensan de esta solución? ¿Les sería útil?
Coméntame en el telegram 😀
Recuerda si algo de lo que escribo te sirve, no dudes en compartirlo, o éntrale al patreon si deseas ayudarme con un cafecin para seguir escribiendo este tipo de babosadas 😀
Zero out