Would "Promise.all" (and other similar functions) be an example of Javascript parallelism?

Asked

Viewed 385 times

8

In Javascript, we have the Promise.all, that solves an array of promises in a single Promise. This process is apparently parallel, since the promises are resolved at the same time, and not in a linear way.

Beyond the Promise.all, other functions such as Promise.allSettled and Promise.race also have a similar behavior of executing promises "at the same time", solving in one Promise.

But that’s really kind of parallelism in Javascript? How it really works?


An example that compares the promises solving themselves in a linear and parallel, respectively:

// Irá demorar 500ms para dobrar o número.
const double = (num) => new Promise((resolve) =>
  setTimeout(() => resolve(num * 2), 500)
);

(async () => {
  const doubles = [];
  
  const start = Date.now();
  for (let i = 1; i <= 5; i++) {
    doubles.push(await double(i));
  }
  
  console.log(doubles);
  console.log(`Finished in ${Date.now() - start}ms.`);
})();

const double = (num) => new Promise((resolve) =>
  setTimeout(() => resolve(num * 2), 500)
);

(async () => {
  const nums = Array.from({ length: 10 }).map((_, i) => i + 1);
  
  const start = Date.now();
  const doubles = await Promise.all(nums.map(double));
  
  console.log(doubles);
  console.log(`Finished in ${Date.now() - start}ms.`);
})();

  • 2

    Javascript is not multithread, so there is no parallelism (which is execution simultaneous). What happens is that the codes are executed alternately, as the callback of the setTimeout other things can be performed. The 1° await says that the return of the function should be waited to then continue the loop, while the 2° creates the promises and then applies the wait, ie in 1° creates and expects the return of each promise before going next, in the other, the wait is applied after all promises are started and are already waiting

1 answer

5


In fact, parallelism (or non-existence of it) resides in the Precedents themselves, not in Promise.all(). A Promise’s work begins when it is created, which Promise.all(doubles) does is create a file that ends its execution as soon as all incoming files (doubles) were finalized.

In the first snippet of code you call

doubles.push(await double(i))

inside the loop, forcing each cycle to wait for the resolution of the Promise, but do not need to do this; could call

doubles.push(double(i))

allowing double() start performing asynchronously, perhaps concurrently; and then do await in the Precedent created with Promise.all(doubles).

One of the great advantages of using Promise.all() is to receive an exception earlier if any Promise fails, in addition to waiting at most for the longest Promise time within doubles.

Node.js has an internal thread pool so that asynchronous blocking operations can run in parallel. But this pool is beyond the reach of Javascript code. Promises and asynchronous operations that are implemented in pure Javascript (without invoking a module written in C++ that could make use of the thread pool) cannot run concurrently.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.