0

I have an array with callbacks functions, so an Array<Function> | Array<AsyncFunction>. I'm trying to find a way calling these callbacks in parallel

I know Promise.all kind of does that, if I had a list of promises. But I have not been successful in making that work with my input

So to add a bit more detail:

Let's say I have an array of anonymous functions like so

let callbacks = [
    () => {console.log('callback')},
    () => {console.log('another callback');
    () => {console.log('final callback');
];

What would be the best way to execute those callbacks in parallel?

Melvin M.
  • 3,280
  • 3
  • 15
  • 23

3 Answers3

1

Javascript is single threaded language by design. So the engine is capable of resolving only one function at the same time.
Those functions are stacked into the call stack and handled by the event loop. That means, even with promises, the engine is processing a single function at a time.
With Promise.all([...]) you delegate the responsability of handling those calls to keep running your code (inside the then method or awaiting) once all the promises are resolved.
This does not mean all the promises are being executed in parallel.


There was a workaround having that behavior by using multi engine systems called Web Workers, https://www.sitepoint.com/javascript-web-workers/

VRoxa
  • 973
  • 6
  • 25
0

If the work that you plan to do in each callback is asynchronous, then .forEach() should work for you.

The .forEach() call will run immediately, starting all your asynchronous calls, and will not wait until the previous async call has been resolved before kicking off the next one. Since they are each asynchronous, they will just get started in the .forEach() loop.

let callbacks = [
    async () => {console.log('callback')},
    async () => {console.log('another callback')},
    async () => {console.log('final callback')},
];

callbacks.forEach(c => c());
raychz
  • 1,085
  • 1
  • 8
  • 24
-1

To create a Promise from a function, just use the new Promise(executor) constructor.

You can do that 'in a bulk' using map on the array.

Then you can use Promise.all() on your array.

let callbacks = [
    () => {console.log('callback')},
    () => {console.log('another callback')},
    () => {console.log('final callback')},
];
Promise.all(callbacks.map(f => new Promise((resolve) => { 
    f(); 
    resolve();
}))).then(() => 
{
    console.log("All resolved.");
})

I encourage you to check the articles on MDN about Promises.

Note that in the above snippet, the callbacks start executing as soon as the promises are created in the callbacks.map. If for some reason you need this to be done in two steps, and you want to create "cold" promises first, this Q&A provides some clues and solutions : Creating a (ES6) promise without starting to resolve it

Also, as VRoxa mentionned, this is not "paralllel" computing (multi-thread), but rather "asynchronous" computing. I assume you were thinking about the latter, since you were mentioning Promise.all. This Q&A can clarify the terms : How to articulate the difference between asynchronous and parallel programming?

Pac0
  • 21,465
  • 8
  • 65
  • 74
  • This will work. But the problem is that we're never resolving any of those promises. So this will basically cause subsequent statements to never be executed. If I await `Promise.all(callbacks.map(f => new Promise(f)))`, we'll never get past that statement because the promises will always be pending – Melvin M. Apr 04 '20 at 01:13
  • @Meru-kun Indeed, the original answer I wrote was not useful. I edited my code to provide a more sensible example, fixing the issue you mentioned. – Pac0 Apr 04 '20 at 13:30