We are thrilled to inform you that Lancecourse is NOW INIT Academy — this aligns our name with our next goals — Read more.

It seems like you are using an ad blocker. To enhance your experience and support our website, please consider:

  1. Signing in to disable ads on our site.
  2. Sign up if you don't have an account yet.
  3. Or, disable your ad blocker by doing this:
    • Click on the ad blocker icon in your browser's toolbar.
    • Select "Pause on this site" or a similar option for INITAcademy.org.

Javascript in 100 bits

Course by zooboole,

Last Updated on 2025-01-28 08:04:00

Lesson 99 – JavaScript Event Loop and Concurrency

JavaScript is single-threaded, which means it can execute one task at a time. However, thanks to the event loop, JavaScript can handle asynchronous operations like network requests, timers, and DOM events efficiently without blocking the main thread.

In this lesson, we’ll break down how the JavaScript Event Loop works, including key concepts like the call stack, web APIs, callback queue, and task/microtask queues.


The Call Stack

The call stack is where JavaScript keeps track of what function is currently running and what function to return control to when the current function finishes.

Example:

function greet() {
    console.log("Hello!");
}

function start() {
    greet();
    console.log("Start done!");
}

start();

Here’s how the stack works:

  1. start() is pushed to the stack.
  2. start() calls greet(), so greet() is pushed to the stack.
  3. greet() finishes and is popped off.
  4. Control returns to start(), which prints "Start done!" and is then popped off.

Web APIs (Browser APIs)

When asynchronous operations like setTimeout, fetch, or event listeners are called, they are handed off to the Web APIs provided by the browser.

These tasks are run outside of the main thread and queued for execution once the call stack is empty.


Callback Queue (Task Queue)

Once a Web API task completes, its callback is sent to the callback queue (also known as the task queue). The event loop checks if the call stack is empty and then pushes the next callback from the queue to the stack.

Example:

console.log("Start");

setTimeout(() => {
    console.log("Timeout callback");
}, 0);

console.log("End");

Output:

Start
End
Timeout callback

Even with setTimeout(..., 0), the callback goes to the task queue, so it runs after the synchronous code.


Microtask Queue

The microtask queue handles promises and queueMicrotask callbacks. It has higher priority than the task queue.

Example with Promise:

console.log("Start");

Promise.resolve().then(() => {
    console.log("Promise resolved");
});

console.log("End");

Output:

Start
End
Promise resolved

Even though it’s asynchronous, Promise.then runs before setTimeout because it's placed in the microtask queue, which runs before the task queue.


Event Loop in Action

The event loop does the following repeatedly:

  1. Check if the call stack is empty.
  2. If yes, process all tasks in the microtask queue.
  3. Then move to the task queue and process one task.
  4. Repeat the cycle.

Summary

  • JavaScript is single-threaded but handles async tasks via the event loop.
  • Call stack handles function execution.
  • Web APIs handle async tasks (like timers, network calls).
  • Microtask queue (Promises) has higher priority than task queue (setTimeout, events).
  • The event loop coordinates when each task is executed.

Try Your Hand

Challenge:

Predict the output of the following code:

console.log("1");

setTimeout(() => console.log("2"), 0);

Promise.resolve().then(() => console.log("3"));

console.log("4");

Expected Output:

1
4
3
2

Explain why the output appears in that order.


Stay curious and keep experimenting with async code!