What is Asynchronous Programming in JavaScript?

Adam Wallace
6 min readMay 28, 2021

In Javascript programming we can write code Synchronously (Sync) or Asynchronously (Async), but what do these terms actually mean? Let us begin with some standard definitions:

  • Synchronous: ‘existing or occurring at the same time’
  • Asynchronous: ‘not existing or occurring at the same time’

So the definitions may not be super enlightening, but it is important to distinguish between the two terms. An important takeaway is that in synchronous programming we execute everything at the same time (within a continuous time interval).

JavaScript is a single threaded language; this means we can only ever do one thing at a time on a single main thread (here is an explanation of what a thread is). If a task is time consuming (such as a function that loads a large file), it can block this single thread and these blocks can cause performance issues. A main thread block within a browser can manifest as a slow or unresponsive user interface.

In asynchronous programming we pass tasks outside of the main thread to execute on another thread (an asynchronous call), this pass off allows continued execution of the javascript file without blocking the main javascript thread. In async programming when we pass a task off to execute elsewhere, we often provide a function to execute when a result is returned at some point in the future (this process is discussed later). Asynchronous code can be difficult to write as you have to be aware of the different orders in which the code may execute and return.

Let us tie-up what we have discussed in this section. When one task T1 starts a second task T2. In Synchronous programming, T2 is guaranteed to be started and executed inside the time slice of T1. T1 “waits” for the ending of T2 and can continue processing afterwards. In this sense, T1 and T2 occur “at the same time. In asynchronous programming, the execution time of T2 is now unrelated to T1. In this sense, the tasks are NOT occurring at the same time (in a continuous time interval). Asynchronous programming is especially useful In JavaScript as we only have the one thread.

Analogy

I always find real world examples helpful in conceptualising programming topics. Here is a great analogy that helps explain the differences between Sync and Async.

Imagine you are making pasta. You have three steps:

  1. Boil and drain the pasta.
  2. Prepare sauce.
  3. Combine pasta and sauce.

Synchronous method

In the synchronous scenario there is only you, one person (thread) doing all the work in sequence. First you boil the pasta, and you stand there watching it boiling. Then you drain it and set it aside. Then you prepare the sauce. When sauce is ready you take the pasta, mix it with the sauce and your dish is ready.

The problem here is inefficiency. Because you were working sequentially in a synchronous manner, you could not work on the sauce while the pasta was boiling. Time was wasted and your pasta got cold while the sauce was being prepared.

Asynchronous method

In this scenario, there is still only one cook (thread), but while the pasta is boiling you go and make your sauce. When the pasta has cooked, you are called-back from making the sauce to drain the pasta, and then you are called-back again to finish the sauce.

This is more efficient now, because you saved time and your pasta did not have to wait for the sauce as long.

Multi-threaded method (I will include this, but multithreading and web workers are not within the scope of this article)

Now, imagine you hire a new cook. Now there are two cooks (threads). While one cook is cooking pasta, the second cook is making the sauce. Is it necessary in this scenario? This is not necessary as making pasta is simple enough to be efficient with asynchronous method and managing multiple cooks is additional overhead. But if you were making a more complicated dish or even more dishes at once, multiple cooks can be useful.

Code Examples

Imagine you want to load some posts when a user first visits a page.

The following is an example of the Synchronous approach:

Sync post load

In the sync example the user is waiting for the post data to arrive from a server before any other tasks can begin. The other tasks being blocked may well be prevent the user from doing or seeing other things in the meantime.

The following is the asynchronous approach:

Async post load

Now we pass a function into the async call (do not worry I cover what is going on here later), this function will run on completion of the asynchronous call. The browser (and consequently the user) is no longer waiting for the post data to arrive. The execution can continue to run the other Tasks() function and provide the previously blocked functionality to the user.

The following example is a mix of asynchronous and synchronous code:

Async programming example

The console at the bottom may not show what you were intuitively expecting, so what’s going on here? The first two logs are synchronous, they are executed immediately. The setTimeout(callback, delay) however is an asynchronous call (details here), these tasks are passed out of the main thread and their execution is delayed (by an amount specified as a parameter). The main thread continues and executes the last two console logs. The asynchronous setTimeout task returns onto the stack to execute after the delay time specified, and after the test.js file has executed all of its functions.

This brings us nicely onto Web APIs, although not part of the standard JavaScript offering (they are not included in the JavaScript engine), they extend JavaScript functionality to perform asynchronous tasks. Using Web APIs some JavaScript jobs can be transferred to other threads (SetTimeout is a Web API).

The async behaviour of the Web APIs works thanks to the event loop. The event loop has its own intricacies including components you might have heard in passing such as the call stack, event loop and callback queue. Basically, the event loop is endlessly running on a single-threaded loop (running on the main JavaScript thread), it listens for different events and executes callback functions on the main thread. A busy main thread means the event loop is not actively running. There is a great video explaining the event loop here: https://www.youtube.com/watch?v=8aGhZQkoFbQ&ab_channel=JSConf.

Asynchronous is not something you would always want to use, in fact it could be detrimental to your codes performance and complexity, for example you would not use it to change a CSS class on an element (this is not a thread intensive task so you would want it executed immediately). It is usually useful for passing off time-consuming, expensive operations and it is often written for you by browser/server API’s (XMLHttpRequest, Node fs module), or third-party libraries (jQuery/Ajax).

So how do we control all of this asynchronous behaviour available to us in Javascript? That is the subject for my next blog post: Callbacks, Promises and Async/Await! [in progress :D]

References

JavaScript for beginners: Async (https://rowanmanning.com/posts/javascript-for-beginners-async/)

JavaScript Promises and Async/Await: As Fast As Possible (https://medium.com/jspoint/javascript-promises-and-async-await-as-fast-as-possible-d7c8c8ff0abc)

Sync and Async definitions (https://softwareengineering.stackexchange.com/questions/396585/the-meaning-of-asynchronous-vs-synchronous)

--

--

Adam Wallace
0 Followers

Professional web developer. ‘We are what we repeatedly do. Excellence then, is not an act, but a habit’ — Aristotle