Assume we have an action that runs on user login (express, node). This is the code that works, written using a lot of callbacks:
checkIfEmailAndPasswordAreSet(email, password, (error, response) => {
if (error) return errorResponse(403, 'validation error', error)
findUserByEmail(email, (error, user) => {
if (error) return errorResponse(500, 'db error', error)
if (!user) return errorResponse(403, 'user not found')
checkUserPassword(user, password, (error, result) => {
if (error) return errorResponse(500, 'bcrypt error', error)
if (!result) return errorResponse(403, 'incorrect password')
updateUserLastLoggedIn(user, (error, response) => {
if (error) return errorResponse(500, 'db error', error)
generateSessionToken(user, (error, token) => {
if (error) return errorResponse(500, 'jwt error', error)
return successResponse(user, token)
})
})
})
})
})
I want to rewrite this code using async/await and avoid callback hell. How to do that?
The first attempt could look like that:
try {
await checkIfEmailAndPasswordAreSet(email, password)
const user = await findUserByEmail(email)
if (!user) throw new Error('user not found')
const result = await checkUserPassword(user, password)
if (!result) throw new Error('incorrect password')
await updateUserLastLoggedIn(user)
const token = await generateSessionToken(user)
return successResponse(user, token)
} catch (e) {
// How to handle the error here?
}
I want to keep the proper error handling, that is if the error was thrown in checkUserPassword
method, I want the response to contain info about this. What should I write in the catch method?
For example, I could wrap every instruction into it's own try / catch block like that:
try {
let user, result
try {
await checkIfEmailAndPasswordAreSet(email, password)
} catch (error) {
throw new Error('This error was thrown in checkIfEmailAndPasswordAreSet')
}
try {
user = await findUserByEmail(email)
} catch (error) {
throw new Error('This error was thrown in findUserByEmail')
}
if (!user) throw new Error('user not found')
...
} catch (error) {
return errorResponse(error)
}
But this code.. probably that's not a callback hell, but I would call it try/catch hell. It takes at least 2 times more rows that the original old fashioned code with callbacks. How to rewrite it to be shorter and take an advantage of async/await?