DEV Community

Dalmo Mendonça
Dalmo Mendonça

Posted on

The Smallest Possible Mistake to make when using Promises

Let's say you have a Promise, you do some stuff with it then just log back when all processing is finished:

const promise = new Promise((res,rej) => setTimeout(res('Resolved'), 2000))

promise
  .then(result => console.log(result))
  .then(console.log('Success!'))
  .catch(console.log('Error!'))

What's wrong with that code? Well, here's the log:

// Success!
// Error!
// Resolved

That is nothing like expected. What happened?

In fact, both then and catch expect functions as arguments. Those console.log()s are just statements, not functions, thus they're immediately evaluated.

The simplest solution is to turn those statements into anonymous functions:

promise
  .then(result => console.log(result))
  .then(() => console.log('Success!'))
  .catch((err) => console.log('Error!'))

// Resolved
// Success!

Keep in mind this is not a quirk of Promises per se, but the language in general. Other functions that take callbacks are also prone to the same mistake:

setTimeout(console.log('Timed out'), 10000)
// 'Timed out' is printed immediately
// Some environments would throw TypeError [ERR_INVALID_CALLBACK]: Callback must be a function

setTimeout(() => console.log('Timed out'), 10000)
// 'Timed out' is printed after 10 seconds

As someone who's learning JS when Promises are the norm, it seems I've sort of skipped this basic lesson on callbacks.

Discussion (2)

Collapse
savagepixie profile image
SavagePixie • Edited

Another thing you can do, when the then statement takes only one function with the return of the promise as its only parameter, is to just write its name, something like this:

promise
  .then(console.log)
Collapse
dalmo profile image
Dalmo Mendonça Author

Yeah I usually do that as well, and in a sense that may have led me to believe then(console.log('smth')) would be okay. Subtle but makes all the difference.