Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
October 10, 2022 01:44 pm GMT

Asynchronous JavaScript Part 1

Welcome to the first post of the two-part series dedicated to exploring Asynchronous programming in JavaScript.

Scope

This article aims to discuss the following:

  • Synchronous behaviour in JavaScript
  • Event Loop and how it achieves asynchronous behaviour.

Introduction

JavaScript is a synchronous, single-threaded programming language, meaning it can only process code instructions one at a time (sequentially). However, an action like requesting data from a server can take an indeterminate amount of time, and if it were to be performed synchronously, blocking would occur.

Blocking is when subsequent operations on the main thread in a JavaScript program are put on hold until the current running operation completes. This causes the browser to freeze and not be able to handle any other user input like scrolling, clicking a button, etc.

To prevent blocking, the browser has unique methods called Web APIs that you can use to gain asynchronicity in JavaScript. Gaining asynchronicity means JavaScript code instructions can now execute in parallel with each other (simultaneously) instead of sequentially. This is useful as it allows the user to continue using the browser normally while other operations are processed in the background.

Web APIs are special methods provided by the browser that help to create more complex programs. e.g.s setTimeout(), fetch(), etc.

Before we dive into the JavaScript asynchronous flow, let's explore the difference between synchronous and asynchronous code execution.

Sychronous Code Execution

sychronous code execution model.jpg

In the above graphical representation:

  • The main thread executes code instructions sequentially (one after the other).
  • After executing F2, an API request is made and the main thread sits idle (gets blocked) till we receive a response and do response handling (F3).

The problem with the synchronous approach is that F4 cannot be executed until we receive a response from the API request. This causes blocking until the API request completes.

Asychronous Code Execution

asynchronous code execution model.jpg

From the above graphical representation:

  • The main thread executes code instructions sequentially.
  • After executing F2, an API request is made and the main thread starts executing F4 even when we haven't received a response from the server yet.
  • After executing F4 and we have a response, we do response handling (F3).

Here it looks like multiple threads are involved in the execution, but the response handling part will be executed only when the main thread is done executing F4. If we get the response before F4 completes execution, the response will be kept on hold in the callback queue (this will be explained later).

In the next section, we will look at how asynchronous code execution happens within the browser with the help of the Event Loop.

The Event Loop

Consider the image below.

JS engine.jpg

In reality, the JavaScript engine always runs inside a hosting environment, which for most developers is a browser or Node.js. Nowadays, JavaScript gets embedded into all kinds of devices, from robots to light bulbs. Every single device represents a different hosting environment for the JavaScript engine. However, the standard representation in all the hosting environments is a built-in mechanism known as the Event Loop. The Event Loop has one simple job: monitoring the call stack and the callback queue. If the call stack is empty, the Event Loop will take the first message from the callback queue and push it to the call stack for execution.

Let's run through a demonstration of the Event Loop at work and also explain the two most essential elements of the Event Loop:

  • Call stack
  • Callback queue (also known as message queue or task queue).

The Event Loop at Work

A JavaScript program that does not make use of a Web API will execute sequentially, in a synchronous manner. This is demonstrated by the example code below.

// example 1.1function one() {  console.log(1);}function two() {  console.log(2);}function three() {  two();  console.log(3);}// call functionsone();two();three();

In the above code example, you defined and wrote function calls to three functions that print numbers to the console.

The output of the function calls will be based on the order in which the functions were called, that is, one(), two(), and then three().

Output

123

However, the program's behaviour completely changes when a Web API is introduced.

Add the setTimeout() Web API method to the second function two().

// example 1.2function one() {  console.log(1);}function two() {  setTimeout(() => {    console.log(2);  }, 5000);}function three() {  console.log(3);}one();two();three();

The setTimeout() method is a Web API to set a timer and perform an action after a specified time. It takes two arguments:

  • the function it will run asynchronously.
  • and the amount of time it will wait before executing that function.

The setTimeout() method needs to be asynchronous; otherwise, the entire browser would remain frozen while waiting.

Now, the output of the above code is shown below:

132

From the results above:

  • It can be seen that two(), now an asynchronous function, was executed only after executing all the top-level synchronous functions. This happens because the JavaScript host environment, in this case, the browser, uses the Event Loop to handle concurrency or parallel events.

JavaScript needs the Event Loop to inform it of when to execute which specific code statement, and the event loop handles this with the help of a call stack and a callback queue.

Call Stack

As JavaScript is a single-threaded programming language, the JavaScript engine has a single call stack capable of performing only one action at a time. The call stack keeps track of the code to be executed and then executes them sequentially.

Let's take a quick look at how our code example with the Web API (example 1.2) will get executed in the call stack.

Refer to the image below for further understanding.

event loop all2.jpg

During the execution of our program in example 1.2, the browser handles the execution in the following order:

  • Add one() to the call stack, execute it and then remove it from the call stack. This will log 1 to the console.
  • Add two() to the call stack and execute it.
  • Add setTimeout() to the call stack, execute it, and remove it from the call stack. This will start a timer as part of the Web APIs and add the anonymous function in setTimeout() to the callback queue after the timer expires.
  • Remove two() from the call stack.
  • Add three() to the stack, execute it and remove it. This will log 3 to the console.
  • After at least 5000 ms, the timer completes and pushes the anonymous function to the Callback Queue.
  • Finally, the event loop checks the callback queue for pending messages, finds the anonymous function from setTimeout(), and then adds it to the call stack for execution when it's empty and done executing three(). This will log 2 to the console, and then the anonymous function will be removed from the call stack.

Adding, executing, and removing items from the call stack works on the Last In, First Out (LIFO) principle, which means that code instruction that comes last in the call stack is executed first and then removed from the call stack.

As seen above, using the setTimeout() Web API introduced the concept of the callback queue, which we will cover next.

Callback Queue

The callback queue serves as a waiting area for code instructions. Whenever the call stack is empty and done executing all the top-level synchronous functions, the event loop will check the callback queue for any waiting messages. Once it finds one, it will add it to the call stack and execute the function in the message.

The callback queue exists because if the timer set in our example were to add the anonymous function directly to the call stack after it expires, it would interrupt whatever function is currently running and cause unpredictable effects.

Conclusion

  • JavaScript is a single-threaded programming language.
  • Blocking can be avoided through asynchronous programming.
  • Asynchronous behaviour in JavaScript can be achieved with the help of Web APIs.
  • The main task of the event loop is to check the emptiness of the call stack and the availability of waiting messages in the callback queue.

In the next and final part of this Asynchronous JavaSscript series, you will learn about the original way of dealing with asynchronous behaviour through callbacks, the ES5 introduction of promises, and the modern practice of using async/await.

I hope this has been a worthwhile read. Kindly share this article and follow me on Twitter @dboatengx for updates on future posts.


Original Link: https://dev.to/dboatengx/asynchronous-javascript-part-1-2o6m

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To