Understanding JavaScript Event Loop, Microtasks and Macrotasks

This article explains JavaScript’s single‑threaded nature, the event loop mechanism, and the distinction between microtasks and macrotasks, illustrating their execution order with detailed code examples and step‑by‑step analysis to help developers grasp asynchronous behavior in front‑end development.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Understanding JavaScript Event Loop, Microtasks and Macrotasks

JavaScript runs on a single thread, so tasks are queued; to avoid blocking, the language distinguishes synchronous and asynchronous tasks, processed via the event loop.

Event Loop

All synchronous tasks run on the main thread; asynchronous tasks place an event in a task queue; when the call stack is empty, the engine pulls events from the queue and executes them, repeating continuously.

Microtasks and Macrotasks

To improve efficiency, tasks are further classified: macrotasks are initiated by the host (e.g., setTimeout, setInterval, setImmediate) and microtasks are created by the JavaScript engine (e.g., Promise.then, MutationObserver, process.nextTick). Promise constructors run synchronously, while their .then callbacks are queued as microtasks.

setTimeout(function () {
  console.log(1);
});

new Promise(function (resolve, reject) {
  console.log(2);
  resolve(3);
}).then(function (val) {
  console.log(val);
  console.log(4);
});

//2 3 4 1

The execution order is: after the call stack clears, microtasks are processed before macrotasks, leading to the observed output 2 3 4 1.

Event Loop Closed Loop Process

When the main thread finishes synchronous code, it repeatedly: executes all microtasks in order, then picks the earliest macrotask, runs its synchronous part, and repeats.

setTimeout(function () {
  console.log(1);
});

new Promise(function (resolve, reject) {
  console.log(2);
  resolve(3);
}).then(function (val) {
  console.log(val);
  console.log(4);
  setTimeout(() {
    console.log(5);
  });
});

//2 3 4 1 5

Adding a macrotask inside a .then callback schedules it for the next loop iteration, so the output becomes 2 3 4 1 5.

Why Design Microtasks

Microtasks allow urgent operations to run before the next macrotask, avoiding unpredictable delays caused by long‑running macrotasks.

Practice Example

console.log("1");

//setTimeout1
setTimeout(function () {
  console.log("2");
  new Promise(function (resolve) {
    console.log("3");
    resolve();
  }).then(function () {
    console.log("4");
  });
  //setTimeout2
  setTimeout(function () {
    console.log("5");
    new Promise(function (resolve) {
      console.log("6");
      resolve();
    }).then(function () {
      console.log("7");
    });
  });
  console.log("14");
});

new Promise(function (resolve) {
  console.log("8");
  resolve();
}).then(function () {
  console.log("9");
});

//setTimeout3
setTimeout(function () {
  console.log("10");
  new Promise(function (resolve) {
    console.log("11");
    resolve();
  }).then(function () {
    console.log("12");
  });
});

console.log("13");

The detailed step‑by‑step execution yields the final console output: 1 8 13 9 2 3 14 4 10 11 12 5 6 7.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaScriptfrontend developmentevent loopmicrotasksmacrotasks
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.