Two dimensional timeline — A way to think about asynchronous JavaScript

To visualise the order of execution of asynchronous operations

Jack Siu
Jack Siu
Jan 8 · 6 min read
Image for post
Image for post

I remember when I first worked in JavaScript, I found it difficult to understand how to correctly handle asynchronous operations. I made some common mistakes like assuming AJAX is synchronous which causes my function always returning undefined. It was also difficult to get used to how setTimeout works. The fact that it does not block the code frustrated me.

It took me a long time to get used to how callback, promises and async/await work. One way I find it useful is to visualise the sequence of the execution in two dimensional timeline.

Synchronous World

Image for post
Image for post

Now, I would like to pause the execution for 2 seconds in JavaScript using function setTimeout. Let me just replace print to console.log and time.sleep to setTimeout.

Everything inside the callback is executed after 2 seconds, great. But wait, why does the console.log(‘End’) run before console.log(‘Timeout’)? I assume the code should be executed line by line. And the 3rd line should not be executed before everything in the 2nd line, including the callback function is executed. My assumption couldn’t have been more wrong in JavaScript.

JavaScript performs non-blocking I/O operation and setTimeout is also non-blocking. the 2nd line does not block execution. After setting a 2 seconds timer, it keeps running and executes the 3rd line. When the 2 seconds timer is finished, the console.log(‘Timeout’) will then be executed.

That is how setTimeout works. But what I want to achieve is to block the execution while waiting for 2 seconds, just like what I did in Python code. There should be another simple API to achieve it. After searching on the Internet for a long time, I can’t find such API. Instead I found some workaround to achieve it.

Image for post
Image for post

I run the code to see if it can block the execution. Yes, it can block the execution. I can see “Timeout” is logged in the console before “End”. It behaves like time.sleep in Python. But when I take a moment to think about what the code does, it can’t block the execution. The little blue circle does not stop but keeps running in the loop. I just can’t stop it.

Asynchronous World

Blocking the thread in the browser can cause the User Interface freeze because it is busily running inside the loop. When a user clicks a button, the click event is queued. However, the thread just can’t escape from the loop before the loop condition is satisfied. Before that, it can’t handle the callback of click event. Because of the fact that JavaScript is single threaded, there is no other thread to handle the click event. Things could be even worse if the thread in NodeJS is blocked. The server will be unable to process subsequent requests while the thread is blocked.

After a long time of struggle, I have to accept the non-blocking behaviour. I have to accept the callback in the 2nd line can happen after the 3rd line is executed, which to me is unintuitive. It makes me ponder how I should visualise the time in a non-blocking way. And I come up with this diagram.

Image for post
Image for post

The blue circle will still execute the code line by line. But the story has not ended. After executing setTimeout, the asynchronous operation will be set to pending state. When the timer is finished, the callback will then be executed in another timeline.

As mentioned before, one mistake I made when I started coding in JavaScript is returning undefined from a function which involves asynchronous operations like retrieving data from AJAX , reading a file from file system, and querying a database. I believe I am not the only one who struggles with this problem as there are some related questions like this, this, and this posted on Stack Overflow. I rethink this kind of mistake in the two dimensional timeline.

Image for post
Image for post

When reading a file from the file system, the data is not immediately available, which causes undefined logged on the first timeline. When the data is available, the code inside the callback will be executed on the second timeline and the file data can be logged on console.

Run asynchronous operations in sequence

In this case, the second asynchronous operation needs to be nested inside the callback of the first asynchronous operation. This deeply nested code reduces readability of code. If the asynchronous operation API supports ES6 promise, the code can be written in async-await format which is synchronous-looking and easier to read. But under the hood, it is still an asynchronous operation so the two dimensional timeline should be same as the code in callback style.

Image for post
Image for post

Run asynchronous operations concurrently

Unlike the voice message example, sometimes the asynchronous operations are independent. Each asynchronous operation does not depend on the callback result of other operations. For example, we want to call a web service, write a file, and insert a record to the database. One way is to just execute the asynchronous one by one in sequence.

Image for post
Image for post

If we execute the code in sequence, the entire execution time is around the sum of execution time of each operation. Since all operations in this example are independent so they can be executed in concurrently, which can greatly reduce the entire execution time.

Instead of awaiting every operation, this time the operation run one after another immediately and passing all promise to Promise.all, which can await multiple promises at once.

Image for post
Image for post

Thanks to the non-blocking I/O nature which I once thought unintuitive, JavaScript can run multiple asynchronous operations concurrently in a few lines of code without dealing with multithreaded programming.

Thank you for reading this post. If you find it hard to understand the execution order of asynchronous operations, I hope the two dimensional timeline can help you.

JavaScript In Plain English

New JavaScript + Web Development articles every day.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store