DEV Community

Cover image for Some Beginner Tips for Concurrency with Async/Await and Promise.all
Shy Alter
Shy Alter

Posted on • Originally published at Medium on

Some Beginner Tips for Concurrency with Async/Await and Promise.all

How you can make good use of concurrency to reduce execution time.

So you are using Async/Await and enjoying all the great benefits of it:

  1. Clean Code
  2. Better error handling
  3. Easy Branching (if/else)
  4. Debugging
  5. Much more…

Yet it’s a good idea not to let the nice and clean syntax take your mind away from concurrency and how you can benefit from running tasks concurrently.


Multitasking

Concurrent computing is a form of computing in which several computations are executed during overlapping time periods — concurrently — instead of sequentially (one completing before the next starts).

I will show the benefits by presenting two cases where concurrency shines.

Case 1: List of tasks

Let’s say you have a list of posts that need to be published on an external service. Before publishing you want to validate some post fields and if they’re OK to publish.

The sequential *solution * 😴

You can iterate over the list and check validation for each post, then if the post is valid proceed and publish it.

This solution works, but you need to pay attention that each post has to wait until the end of the previous one to finish.

There is no reason why we should not execute all of them simultaneously.

The concurrent *solution * 😎

First we will create a publishing pipeline: validate _ _ publish

Second, we will map all our posts to the pipeline and get back a list of tasks (Promises). Now we can call “Promise.all” to wait until all of the pipelines are done. Execution time has been reduced to almost one pipeline because each pipeline is running independently from one other.

If you are dealing with very long sequences of posts it’s a good idea to split the pipelines into chunks and execute them one by one.


Posting time: 200ms

Number of posts: 20

Seq solution: 200ms * 20 = 4sec 

Concurrent solution: approximately 200ms

4sec vs 200ms - **20x faster**
Enter fullscreen mode Exit fullscreen mode

Case 2: Independent sources

Sometimes you relay on several independent data sources, same as having multiple arguments for a function. they are not blocking each other and can be fetched in concurrent.

Now let’s imagine you need to compare all users’ payments, invoices and receipts in your platform.

The sequential *solution * 😴

You can get each resource one by one and then use them.

But now each data source will be fetched only after the previous one is finished, causing a slower execution time.

A concurrent *solution * 😎

Create 3 different tasks and wait until all of them are done.

Here all of the calls are made in concurrent, which means we now have a faster preparation time, especially when calls are expensive in terms of time.


Get payments: 900ms

Get invoices: 800ms

Get receipts: 2000ms

Seq solution: 900ms + 800ms + 2000ms = 3700ms = 3.7s

Concurrent solution: Max(900ms, 800ms, 2000ms) = 2000ms = 2sec

3.7s vs 2sec - **1.85x faster**
Enter fullscreen mode Exit fullscreen mode

Conclusion

Async/Await can give us a lot of benefits in terms of readability and error handling, but we should not forget to use this feature wisely and always look for the tasks that could be handled concurrently.

  • Always try to think which calls are non blocking and which ones have to run one by one.
  • Every time you’re finding yourself writing a loop with await try to figure out if you can use Promise.all based on the dependency of the calls.

Top comments (0)