JavaScript Promise chaining

Imagine you want to:

  • Request a user from a server (and wait for the user information).
  • Get the user's friends from the server (and wait for the information).
  • Show the user name and the user friends' names at the same time.

This is how you do it with a Promise:

// Get the user Jeffrey after waiting 1 second.
const getUser = (resolve) => {
  setTimeout(() => resolve({ name: 'Jeffrey' }), 1000);
};

// Get Jeffrey's friends after waiting 2 seconds.
const getFriends = (resolve) => {
  setTimeout(() => resolve(['Donny', 'Walter', 'Maude']), 2000);
};

new Promise(getUser) // 1
  .then((result) => console.log('User: ' + result.name)) // 2
  .then((result) => new Promise(getFriends)) // 3
  .then((result) => console.log('Friends: ' + result)); // 4

// result:
// User: Jeffrey
// Friends: Donny, Walter, Maude

What is going on?

  1. The Promise is created and it does a request to get the user.
  2. Then, after waiting 2 seconds, it outputs "User: Jeffrey"
  3. Then, it requests Jeffrey's friends names.
  4. Then, it outputs Jeffrey's friends names.

You see the then methods called one after the other? That is chaining!

Although the example is fake, this need of getting something based on a first request happens a lot.

Notice that:

  • We don't need to store the promise in a variable. We can call the then method right after the Promise creation (point 1).
  • You can pass whatever you wish to a resolve or reject function (e.g. array, object, error objects).

Example of implementing wait with a Promise

If you used a lot of callbacks before, you are probably already convinced about Promises. If not, let's see how we can create a wait function:

const wait = (ms) => new Promise((res) => setTimeout(res, ms));

wait(2000)
  .then(() => console.log('hey'))
  .then(() => wait(1000))
  .then(() => console.log('ho'));

How cool is that?! The code is written almost like synchronous code!

Notice that after a Promise calls the resolve or reject function, the promise state won't change again. That is why a new Promise needs to be created every time we call the wait function.

We'll talk about other Promise rules later.

Questions

What's the output?

const w = (ms) => new Promise((res) => setTimeout(() => res(), ms));
const f1 = () => console.log(1);

w(2000).then(f1);

What's the output?

const f = (ms) => new Promise((res) => setTimeout(res, ms));

f(1000)
  .then(() => console.log('hi'))
  .then(() => f(2000))
  .then(() => console.log('there'));