Table of contents
1.
Introduction
2.
Event Loop
2.1.
General Algorithm
3.
Microtasks
3.1.
Implementation
3.2.
Output
4.
Macrotasks
4.1.
Implementation
4.2.
Output
5.
FAQs
5.1.
In JavaScript, what is the difference between microtasks and tasks?
5.2.
What is the difference between a task queue and a call stack?
5.3.
Is a call stack similar to a queue?
5.4.
What happens when the maximum call stack size is reached?
6.
Conclusion
Last Updated: Mar 27, 2024

MicroTask and MacroTask in Javascript

Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Let’s start with a fun fact. Are you aware of the fact that JavaScript executes all operations on a single thread, but it gives the illusion of multi-threading through the use of a few sophisticated data structures? The runtime model of JavaScript is based on an event loop, which executes the code, collects and processes events, and executes queued sub-tasks.

In this article, we will learn about how Javascript performs task execution by dividing them into “microtasks” and “macrotasks.

After reading this article you will be able to grasp basic concepts of the event loop, microtasks and “macrotasks” in JavaScript. So, let’s get started by learning about the event loop.

Event Loop

JavaScript is a synchronous programming language that works in a single thread. But, in reality, what does it imply? It indicates that the main thread, where JavaScript code is executed, executes one line at a time, with no option of parallel execution.

(JavaScript engine executes one line at a time)


The Event loop is only a watchdog that ensures that the Call Stack and Callback Queue are in constant communication. It first determines whether the call stack is free, and then informs the user of the callback queue. The callback function is then passed to the Call stack, which executes it. The call stack is out and the global execution context is free once all of the callback functions have been performed.

( Eventloop, Source: medium.com )

General Algorithm

The event loop is a simple notion. The JavaScript engine waits for tasks, executes them, and then sleeps, waiting for more.

The engine's general algorithm is as follows:

  1. While there are tasks to be completed:
    → Execute them, begin from the oldest.
  2. Sleep until another task comes.
    → Go to step 1.

The main reason for using microtasks is to assure consistent task ordering, even when results or data are provided synchronously, while lowering the possibility of user-visible delays in operations.
The macro-task queue, on the other hand, works in the same way as the task queue. The task queue is used for synchronous statements, whereas the macro-task queue is used for asynchronous statements. New events may be registered and then created and added to the queue when a (macro) task in the macro-task queue is executed.

Check this out, Abstract class in java

Microtasks

In the above section, we have learned about the event loop in JavaScript. Now, let’s learn about Microtask.

A microtask is a tiny function that is run after the function or programme that produced it has exited and only if the JavaScript execution stack is empty, but before the user agent returns control to the event loop that controls the script's execution environment. 

This event loop could be the browser's main event loop or the event loop that controls a web worker. This allows the specified function to run without the risk of interfering with the execution of another script, while also ensuring that the microtask runs before the user agent has a chance to react to the microtask's actions.

Examples: process.nextTick, Promises, queueMicrotask, MutationObserver

Implementation

Before any other event handling, rendering, or “macrotask” occurs, all microtasks are performed. This is significant because it ensures that the application environment remains essentially the same (no changes in mouse coordinates, no new network data, etc.) between microtasks.

We can use "queueMicrotask" to plan a function to run asynchronously (after the current code) but before updates are rendered or new events are handled.

Here's an example with a "counting progress bar" that's similar to the previous one, but instead of "setTimeout," queueMicrotask is used. It renders at the very end, as you can see. Similarly to the synchronous code:

<!-- JavaScript queueMicrotask() function -->
<div id="progress"></div>

<script>
    //Queue a microtask to update the progress bar
    function function1() {
        var progress = document.getElementById("progress");
        //Update the progress bar
        var i = 0;
        var interval = setInterval(function() {
            progress.innerHTML = i;
            i++;
            if (i > 100) {
                clearInterval(interval);
            }
        }, 100);
    }
    window.queueMicrotask(function1());
    //queueMicrotask() is a function that runs after the current task
</script>

Output

The output is taken after the count reaches 100.

You can practice by yourself with the help of Online Javascript Compiler for better understanding.

Macrotasks

macrotask is a tiny function that runs after the JavaScript execution stack and microtask have both been cleared. 

A macro-task represents a separate and independent piece of task. The JavaScript code is always executed here in macrotask queue, and the microtask queue is always empty. The macrotask queue is frequently confused with the task queue or the event queue. The macrotask queue, on the other hand, works in the same way as the task queue. The task queue is used for synchronous statements, whereas the macrotask queue is utilised for asynchronous statements.

In a single macrotask execution cycle, all logged microtasks are processed in one fell swoop. The macrotask queue, on the other hand, has a lower priority. Parsing HTML, producing DOM, executing main thread JavaScript code, and other events like page loading, input, network events, timer events, and so on are all macrotasks.

Example: setTimeout, setImmediate, requestAnimationFrame, setInterval, requestAnimationFrame, etc

Implementation

We will implement the setTimeout() macrotask function to see, how the macrotask works.

<!-- JavaScript setTimeout function macrotask -->
    <script>
        (function() {
          // Start of Async Call
        console.log('START');
        setTimeout(function cb() {
          console.log('Callback 1: A message from Callback.');
        });
        // setTimeout()
        console.log('A message from main thread.');
        setTimeout(function cb1() {
          console.log('Callback 2: A message from Callback');
        }, 0);
        // print end to the console
        console.log('END');

        })();
    </script>

The callback will not start after zero milliseconds if the delay is zero. When setTimeout is called with a delay of 0 (zero) milliseconds, the callback function is not executed after the specified interval. In the above example we have demonstrated the setTimeout() function.

Output

In the above example, the alert “Hello” is displayed after a 3000 milliseconds delay.

Recommended Topic: Fibonacci Series in Java  and Fibonacci Series in JavaScript

FAQs

In JavaScript, what is the difference between microtasks and tasks?

A macro task is a collection of distinct and independent tasks. Microtasks are minor tasks that update the state of an application and should be completed before the browser moves on to other activities, such as re-rendering the user interface. Promise callbacks and DOM modification changes are examples of microtasks.

What is the difference between a task queue and a call stack?

It's up to it to check whether the callstack is empty and whether the task queue has any pending tasks to complete. If the callstack is empty, it will push the job from the queue to the callstack, where it will be processed.

Is a call stack similar to a queue?

This type of stack is often referred to as an execution stack, control stack, run-time stack, or machine stack, and is frequently abbreviated as "the stack." In summary, a job queue is a list of tasks to be completed (typically maintained persistently), while a call stack is a collection of functions.

What happens when the maximum call stack size is reached?

When there are too many function calls or a function lacks a base case, the JavaScript exception "too much recursion" or "Maximum call stack size exceeded" occurs.

Conclusion

In this article, we have covered “microtasks” and “macrotasks” in the event loop. To sum up the whole process of the event loop, we check the following:

Recommended Reading:

Difference Between Analog and Digital Computer

  • ONLY when the stack is empty, check what's going on in the queues above and execute everything from the bottom to the top of the stack.
  • Check the micro stack and, if necessary, execute everything there with the help of the stack, one micro-task at a time, until the microtask queue is empty or no longer requires execution, and ONLY THEN check the macro stack.
  • Check the macro stack and, if necessary, execute everything there using the stack.

We hope that this blog has helped you enhance your knowledge regarding microtasks and “macrotasks” in the JavaScript event loop and if you would like to learn more, check out our articles on Javascript BOMEventloop in JavaScriptJavaScript DOMFunction Execution in JavaScriptModules in JavaScriptScreen Object in JavaScript. Do upvote our blog to help other ninjas grow.

Head over to our practice platform Coding Ninjas Studio to practice top problems, attempt mock tests, read interview experiences, interview bundle, follow guided paths for placement preparations and much more.!

Happy Reading!
 

Live masterclass