The `Promise.all()` Function in JavaScript

Jan 20, 2020

The Promise.all() function converts an array of promises into a single promise that fulfills when all the promises in the original array fulfill.

Here's an example of using Promise.all() to wrap an array of promises:

// `p1` is immediately fulfilled with value `1`
const p1 = Promise.resolve(1);
// `p2` will be fulfilled with value `2` after 100ms
const p2 = new Promise(resolve => setTimeout(() => resolve(2), 100));

const pAll = Promise.all([p1, p2]);
pAll instanceof Promise; // true

const arr = await pAll;

Array.isArray(arr); // true
arr[0]; // 1
arr[1]; // 2

Parallel Execution of Async Functions

When used with async functions, Promise.all() lets you execute code in parallel. Pass an array of async function calls to Promise.all(), and JavaScript will execute the async functions in parallel.

Suppose you have two async functions getName() and getAge(). Here's how you can use Promise.all() to execute them in parallel:

async function getName() {
  await new Promise(resolve => setTimeout(resolve, 200));

  return 'Jean-Luc Picard';
}

async function getAge() {
  await new Promise(resolve => setTimeout(resolve, 200));

  return 59;
}

const start = Date.now();
const [name, age] = await Promise.all([getName(), getAge()]);
const end = Date.now();

name; // 'Jean-Luc Picard'
age; // 59

end - start; // Approximately 200

Error Case

If one of the promises rejects, the promise returned by Promise.all() rejects immediately with the same error.

const success = new Promise(resolve => setTimeout(() => resolve('OK'), 100));
const fail = new Promise((resolve, reject) => {
  setTimeout(() => reject(new Error('Oops')), 100);
});

try {
  await Promise.all([success, fail]);
} catch (err) {
  err.message; // 'Oops'
}

Note that, since promises are not cancellable, each individual promise continues execution, even if one of them errors out. If you pass an array of async functions and one of the async functions throws an error, Promise.all() will reject immediately with that error. But the other functions will continue executing.

let finished = false;

const success = async function() {
  await new Promise(resolve => setTimeout(resolve, 100));

  finished = true;
  return 'OK';
}
const fail = async function() {
  await new Promise(resolve => setTimeout(resolve, 10));
  throw new Error('Oops');
}
try {
  await Promise.all([success(), fail()]);
} catch (err) {
  err.message; // 'Oops'

  // `Promise.all()` fails fast because `fail()` threw an
  // error, but `success()` is still running.
  finished; // false

  // If you wait, `success()` will set `finished`
  await new Promise(resolve => setTimeout(resolve, 100));
  finished; // true
}

Getting Fancy with Generators

The Promise.all() function doesn't limit you to arrays, the first parameter can be any JavaScript iterable. Arrays are iterables, and so are generator functions. Which means you can pass in a generator that yields promises, and Promise.all() will bundle all the yielded promises into a single promise.

const generatorFn = function*() {
  for (let i = 1; i <= 5; ++i) {
    yield Promise.resolve(i);
  }
}

const arr = await Promise.all(generatorFn());

arr; // [1, 2, 3, 4, 5]

Async/await is the future of concurrency in JavaScript. "Mastering Async/Await" teaches you how to build frontend and backend apps using async/await in just a few hours. Get your copy!

Did you find this tutorial useful? Say thanks by starring our repo on GitHub!

More Fundamentals Tutorials