Member-only story
Dealing with asynchronous logic is an unavoidable part of modern JavaScript programming. Callbacks used to be the standard approach, but promise-based async/await syntax has become the modern solution to write asynchronous code that is easy to reason about.
Taming Callback Hell with Promises
Callback-based asynchronous code leads to the dreaded “callback hell” with poor code readability:
function getUser(id, callback) {
// imagines async operation
let user = {
id: id,
name: 'John'
}
callback(user)
}
getUser(1, (user) => {
getUserPreferences(user, (prefs) => {
getPlanDetails(prefs, (plan) => {
// nasty nested callbacks!
})
})
})
Promises abstract callbacks away into chainable operations:
function getUser(id) {
// promise implementation
return promiseWithUser;
}
getUser(1)
.then(user => getUserPreferences(user))
.then(prefs => getPlanDetails(prefs))
.then(plan => {
// much cleaner!
})
But even with promises, the pyramid shape indicates something is still off from typical synchronous code.