DEV Community

Cover image for Understanding the Event Loop in JavaScript: Microtasks, Macrotasks, and Asynchronous Execution
Nishanthan K
Nishanthan K

Posted on

Understanding the Event Loop in JavaScript: Microtasks, Macrotasks, and Asynchronous Execution

Event Loop

  • Javascript is an single threaded language which means it can be able to handle only one task at a time (synchronous task).
  • But if the task takes more time to compile and execute then it would block the user to make any interaction in the web page like scrolling, clicking etc.
  • So to avoid this block of execution, Javascript has to handle tasks simultaneously on some other thread.
  • Javascript uses web api with the support of browser to handle asynchronous tasks on other thread provided by browser
  • Tasks handled by web api’s are classified into Microtasks and Macrotasks.
  • The process of deciding the order of the execution of the task is called Event Loop.
  • Event Loop has different groups
    • Call Stack
    • Web Api
    • Microtask Queue
    • Macrotask Queue (Callback Queue)

Web API

  • Web API is provided by browsers to handle asynchronous tasks so that Javascript will handle the sychronous task in its thread. Because Javascript was single threaded.
  • So Javascript simply send all async tasks to the Web API and Web API will take over this.
  • List of API’s powered by Web API
    • Browser Api
      • DOM Api
      • Fetch Api
      • Local Storage Api
      • Geo Location Api
      • Navigator Api
    • External Api
      • These are the third party services that the browser access through Javascript typically over HTTPS.
      • REST or GraphQL to fetch data from external source or server.

Call Stack

  • This is the single thread where the Javascript runs the program.
  • It is an stack data structure so it is LIFO (Last In First Out).
  • But only the sync task is handled here, if any async found it will be moved to web api
  • Once that async task is processed, it will be moved to either Microtask or Macrotask.

Microtask Queue

  • Microtasks are the high priority tasks that are generally need to be executed as soon as possible.
  • Because it holds tasks fetching data from database, handling promises and user defined async functions.
  • As these tasks all are more based on logic and functionality.
  • So once the call stack is empty, tasks in Microtasks queue will be moved to call stack and tasks are executed in the same order it was added to the Microtask queue.

    Example

    • Let’s say we have 3 tasks in Microtask, first task takes 5sec to complete, second task takes 2sec to complete, 3rd task takes 1sec complete.
    • Eventhough 3rd task was completed in 1sec it will not be executed before task 1 and 2.
    • All tasks will be processed simultaneously but the order of execution is task1, task2, task3.

Macrotask (Callback Queue)

  • Macrotasks are lower priority and large scale operations (which took more time to process).
  • Tasks like timers, event listeners (click, scroll etc) and UI updates.
  • These tasks will be get executed in the order of processed not added.
  • UI-Related Tasks: Like rendering or user interactions (e.g., handling click, scroll, or input events).
  • Timers: setTimeout(), setInterval(), etc.
  • I/O Operations: File reading, network requests (e.g., XMLHttpRequest).
  • Rendering Tasks: Some browsers schedule UI rendering (repaint/reflow) as macrotasks.

Order of Execution

  • JS start its execution line by line. All sync tasks are handled on its Main thread and tasks which will took more time to process and other async tasks are moved to web api.
  • Then tasks are categorised and moved to either Microtask / Macrotask queue.
  • Once callstack is empty, Microtasks will starts its execution. After completion of all Microtasks, Macrotasks will starts its execution.
  • If any new tasks is added to Microtasks while executing Macrotasks then that Microtask will be processed and executed before moving to the next Macrotask in the queue.

Example

console.log('Start'); // 1

setTimeout(() => {
  console.log('Macrotask 1'); // 4
}, 0);

fetch('https://api.example.com/data')
  .then(response => {
    console.log('Microtask 1'); // 2
  })
  .catch(error => {
    console.log('Error'); // Error handling
  });

Promise.resolve()
  .then(() => {
    console.log('Microtask 2'); // 3
  });

console.log('End'); // 5

// Final Output
Start
End
Microtask 1
Microtask 2
Macrotask 1
Enter fullscreen mode Exit fullscreen mode
  • Start (synchronous) → Call Stack
  • Microtask 1 (from fetch()) → moved to Microtasks Queue
  • Microtask 2 (from Promise.resolve()) → moved to Microtasks Queue
  • End (synchronous) → Call Stack
  • Microtasks Queue is processed:
    • Microtask 1 → Logs 'Microtask 1'
    • Microtask 2 → Logs 'Microtask 2'
  • Macrotasks Queue is processed:
    • Macrotask 1 → Logs 'Macrotask 1

Summary

  • JavaScript is a single-threaded language, meaning it can handle only one task at a time in a synchronous manner. However, for tasks that take longer (like fetching data), JavaScript uses Web APIs provided by the browser to manage these tasks asynchronously, preventing the UI from being blocked.
  • Key components in handling these tasks are:
    • Call Stack: Executes synchronous tasks in a Last-In-First-Out (LIFO) manner. If an asynchronous task is encountered, it is sent to the Web API for processing.
    • Web APIs: Used to handle asynchronous tasks such as HTTP requests, timers, and DOM events, ensuring JavaScript remains non-blocking.
    • Microtasks: High-priority tasks like handling Promises, executed before macrotasks when the call stack is empty.
    • Macrotasks (Callback Queue): Lower-priority tasks like timers (setTimeout), event listeners, and UI updates. Executed after all microtasks have finished.
    • Event Loop: The mechanism that decides the order of task execution. It continuously checks the call stack, microtask queue, and macrotask queue to manage task execution.

Important Note

  • While executing the tasks in callback queue (macrotask), if any new microtask was added then that new microtasks was processed before proceeding with the next macrotask.

Commonly Asked Interview Questions

  • What is the Event Loop in JavaScript, and how does it work?
  • What are microtasks and macrotasks in JavaScript? How are they different?
  • Explain how setTimeout and Promises are handled in the Event Loop.

Top comments (0)