March 22, 2021

How to run Async/Await in Parallel or serial with JavaScript

How to run Async/Await in Parallel or serial with JavaScript

In this tutorial I will show you how you can easily run async/await in parallel. It seems to me that we often forget the power of async await, which comes from being able to run multiple async tasks/jobs/functions at the same time.

In order for us to make use of this, all we need to do is use Promise.all(). Let's take a look at an example.

First things first, I am going to create a simple sleep function which will look like this:

async function sleep(time = 1) {
	const sleepMilliseconds = time * 1000
	
	return new Promise(resolve => {
		setTimeout(() => {
			resolve(`Slept for: ${sleepMilliseconds}ms`)
		}, sleepMilliseconds)
	})
}

Ok, now that we have a sleep function that can simulate some async functionality, let's look at how we can run this in parallel.

I have created a very simple function that will call the sleep function three times:

async function main() {
	// 1. 
	console.time('main')

	// 2.
	const [firstCall, secondCall, thirdCall] = await Promise.all([
		sleep(1), 
		sleep(2),
		sleep(3)
	])
	console.log(`First call: ${firstCall}`)
	console.log(`Second call: ${secondCall}`)
	console.log(`Third call: ${thirdCall}`)

	// 3.
	console.timeEnd('main')
}

main()

Let's run through the above code.

  1. We start a timer, this will allow us to time the code to see how long the code will run for.
  2. The solution. In order to run multiple async/await calls in parallel, all we need to do is add the calls to an array, and then pass that array as an argument to Promise.all(). Promise.all() will wait for all the provided async calls to be resolved before it carries on(see Conclusion for caveat).
  3. Call console.timeEnd() to stop the timer, this will also print out how long the code between console.time() and console.timeEnd() has taken to run.

If we run this code, we should see something similar to this:

First call: Slept for: 1000ms
Second call: Slept for: 2000ms
Third call: Slept for: 3000ms
main: 3011.047ms

As we can see from the output, all three sleep functions run and they print out how long they have run for. We can also see how long the main function has run for, just over 3000ms. This shows that we are running these tasks in parallel, if we weren't, the main function would have run for about 6000ms because it would need to wait for each sleep function to complete before it could run the next sleep function.

To test this out, update the main function with the following code:

async function main() {
	// 1. 
	console.time('main')

	// 2.
	console.log(await sleep(1))
	console.log(await sleep(2))
	console.log(await sleep(3))

	// 3.
	console.timeEnd('main')
}

main()

If we run the above code we should see an output that is similar to the following:

Slept for: 1000ms
Slept for: 2000ms
Slept for: 3000ms
main: 6019.011ms
You can find the full source code here.

Conclusion

Running async/await code in parallel is very easy with JavaScript, all we need to use is Promise.all(). There is one thing to note though, Promise.all() will fail as soon as any of the async functions we have passed to gets rejected. If you don't want this fast failing behaviour, you can use Promise.allSettled() instead of Promise.all().

You can find the full source code here.