How can JavaScript be asynchronous and single-threaded at the same time?

Mastering JavaScript Series

Samim Yaquby
4 min readMar 4, 2019

So if you are completely new to this question, in computer science, thread of execution is the sequence or amount of programmed instructions that can be processed independently at a given time. There are two types types of threading, single threading and multi-threading. JavaScript is a single threaded programming language, Java or C# are multi-threaded programming languages.

What this means is that JavaScript can only run one instruction at a time while Java could run multiple instructions concurrently.

A side note here, for those who would argue that programming languages themselves aren't usually classified based on threads, well I agree, but if a programing language can support for running code in parallel they are multi-threaded, otherwise we can call them single-threaded. You can always run a multithreaded programming language in single thread, but you cant do the opposite. In the end they are practically two different types of programing languages.

Back to topic. So the question is: if JavaScript can run only one instruction at a time, it should be synchronous? Not asynchronous. Because synchronous means a bunch of commands in sequence, right? How can JavaScript be asynchronous and single-threaded at the same time?

Let’s understand this.

Event Loop:

Most of the websites work this way, or at least should be programmed to work this way: Once the user visits a page, they should readily see a user interface. Then they can interact with the interface, by clicking on something, typing something, or just by simply moving their mouse, and the website has to respond accordingly. Also, it is not just the user generated events, the programer could also target some other events to provide customized user experience, like:

  • Browser events, such as when a page is finished loading
  • Network events, response on HTTP request
  • Timer events, timeouts and intervals

These events are at our disposal to target as a programer. We can develop handlers for them and specify what happens on each of these events. The JavaScript engine then takes our handlers and automatically manages them with the help of a callback queue, which practically works like a loop. New things go to the end of the queue and older things are at the head of the queue — FIFO. This circulating process is metaphorically called the event loop. The loop keeps rotating through the tasks in a queue, and performs a task whenever the criteria for it is met. It removes that particular task and continues with what remains in the queue. Lets look at this example:

Here we created two handlers:

The first one will print into console a message that reads clicked, if we click the button.

The second one is for when the page loads. Every time the page is loaded, right after, the console prints thanks for waiting for this page to load. But, it will only print clicked if we click the button. Notice, in the code, the function is written and assigned a handler before the onload event. But, it will only execute its handler when the criteria is met. Asynchronicity doesn’t necessarily mean multi-threadedness. Since these events can happen at unpredictable times and in unpredictable order, we say that the invocation of their handling functions are asynchronous.

Let’s understand this further with a very English example.

Think of a Starbucks in a very English suburb, where people are notorious for forming lines. The Starbucks is small just like the village. There is only one person at the counter and one person behind her preparing the orders. The lady goes through a queue of 10 people one morning. She takes the customers’ orders. Some of their orders doesn’t need preparation, like people ordering the over-the-counter almond snacks. Every time a customers asks for those almonds, the barista gives it to them right away and says “have a good day” to them as they leave. Then, as she takes the rest of the orders some of which need to be prepared.

The customers whose orders need to be prepared form a separate line the already-ordered. And then each of those customers comes forward and sees if their drink is prepared, if they had ordered a regular coffee, chances are it is already prepared, the barista hands it to them and they leave. If it is some other complicated drink, the customer goes to the back of the line and lets the next person check if his drink is ready, by this time a moderately complicated drink is ready and the next customer happens to be to owner, he grabs his drink and leaves. But, the rest of the line keeps rotating. This is a very English place so they love making queues and they don’t mind rotating. Gradually the least complicated orders gets finished first, and the ones that take a little longer go next, and the most complicated ones go last. Once the final guy who had ordered Triple, Venti, Half Sweet, Non-Fat, Caramel Macchiato gets his drink, the queue is over (the event loop ends).

“an Englishman, even if he is alone, forms an orderly queue of one”, Hungarian-born British author George Mikes.

Notice what happened here. The person at the counter served one person at all times. They never served two people at the same time. So at the end of the day the whole process was asynchronous and single-threaded at the same time. Just like our JavaScript processing.

--

--

Samim Yaquby

I am Sam. I code, paint, write, cook, breath, and lift.