For the love of Promises, stop nesting your chains.then()

I’ve been spending a lot of time in some express JS applications lately. I love express, but generally only when I can work with ES7 syntax.

However, lately I’ve been tackling deep, nested, unreadable promise chains.

app.use((req, res) => {
  runSomeDatabaseCode().then((response) => {
    const newResponse = response.manipulate();
    runSomeAPICode(newResponse).then((data) => {
      if (!data) throw new Error("It Broke");
      res.status(200).send(data)
    }).catch(err => res(500).send('Error'))
  }).catch(err => res(500).send('Error'))
});

For the love of all things asynchronous, please tidy this up. The solution in this instance is quite simple — linear promise chains.

app.use((req, res) => {
  new Promise(r => r()) // Just an empty promise to start the structure
  .then(() => new Promise((resolve, reject) => {
    runSomeDatabaseCode()
    .then(response => {
      const newResponse = response.manipulate();
      resolve(newResponse) // Pass the response to the next in the chain
    })
    .catch(error => {
      reject(error)
    })
  }))
  .then((newResponse) => new Promise((resolve, reject) => {
    runSomeAPICode(newResponse)
    .then(data => {
      if (!data) throw new Error('It Broke')
      resolve(data)
    })
  }))
  .then(data => {
    res.status(200).send(data); // resolve to express
  })
  .catch(err => {
    res.status(500).send(err); // resolve errors to express
  })
})

These linear structures are much better as they free up the scope for your functions, remove unnecessary repetition in code and generally allow a better reading experience with less left-right scrolling.

For other cool Promise-related stuff, check out Bluebird. Developers will thank you for it when they are reading your beautifully structured code.

 
1
Kudos
 
1
Kudos

Now read this

JavaScript—async vs defer

My attempt at being helpful—it’s annoying I have to explain this. There has been a mild amount of confusion regarding how Async and Defer work when including scripts. This is kind of necessary if you have rather chunky scripts, or... Continue →