For more tips like this, sign up to the weekly newsletter!

Pass multiple values through Promise chains

A Promise, just like a function, returns a single value, that is passed to the then() callback. But what if you need to pass multiple values down the chain?

The solution is collection types. Return an Array with the values:

Promise.resolve()
  .then(() => {
    return [1, 2]
  })
  .then((res) => {
    // res[0] => 1
    // res[1] => 2
  })

You can also use array destructuring to add some syntactic sugar:

Promise.resolve()
  .then(() => {
    return [1, 2];
  })
  .then(([first, second]) => {
    // first => 1
    // second => 2
  })

The problem with passing arrays down the chain is they are ordering-sensitive. You need to know which values are on which indices, and that can quickly become a mess if you pass down several values.

As an alternative, use objects and object destructuring instead of arrays:

Promise.resolve()
  .then(() => {
    return {first: 1, second: 2};
  })
  .then(({first, second}) => {
    // first => 1
    // second => 2
  })

Using objects removes the ordering issue, and name the values explicitly.

Return multiple Promises

But Promises differ from functions, as they unpack returned Promises. But if you return an array or an object with Promise values, they are passed as-is down the chain:

Promise.resolve()
  .then(() => {
    return {first: Promise.resolve(1), second: Promise.resolve(2)};
  })
  .then(({first, second}) => { 
    // first => Promise
    // second => Promise
  });

To handle this, you need to resolve them manually before returning:

Promise.resolve()
  .then(() => {
    return Promise.all([Promise.resolve(1), Promise.resolve(2)]).then(([first, second]) => {
      return {first, second};
    });
  })
  .then(({first, second}) => { 
    // first => 1
    // second => 2
  });
Try it
Learn more: