Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

JS Puzzles · Const

Promise resolution order

Promise handlers are deferred to the microtask queue, even when a promise is already settled. They run after current synchronous code and in FIFO order, before the event loop advances to later macrotasks.

How it works

Promise handlers are never run immediately, even when their promises are already settled. They are queued as microtasks, and the engine runs queued handlers only after the current synchronous code finishes; a chained handler is queued when its preceding handler completes.

Syntax

promise.then(onFulfilled, onRejected)

Key points

  • Promise-related microtasks execute in FIFO order.
  • A queued promise handler waits until the current synchronous execution has finished.
  • Settling a promise schedules its registered handlers instead of invoking them immediately.
  • Promise reactions consistently pass through the promise-jobs, or microtask, queue.
  • Handlers run only after the current synchronous code completes.
  • When several handlers are queued, earlier enqueued reactions precede later ones.

Common mistakes

  • An already-resolved promise does not make its handler synchronous; code after the registration runs first.
  • Each handler in a chain gets its own asynchronous turn rather than the whole chain executing as one synchronous operation.
  • A large or self-extending microtask queue can delay timers, rendering, and other event handling.

Example: Promise handlers run through the microtask queue

const log = [];

Promise.resolve().then(() => {
  log.push("first");
  Promise.resolve().then(() => log.push("nested"));
});

Promise.resolve().then(() => log.push("second"));
log.push("sync");

setTimeout(() => console.log(log), 0);
// ["sync", "first", "second", "nested"]

Synchronous code runs first. Promise handlers then run in FIFO order; the nested handler is added after the existing second handler, so it runs last among these microtasks.

When to use it

Debug asynchronous ordering

Predicting console output in code that mixes synchronous statements, promises, and timers.

Sequence promise chains

Ensuring dependent asynchronous steps execute only after earlier results settle.

Schedule microtasks

Deferring a small callback until the current call stack is clear without creating a timer.

Interview questions

QWhy does Promise.resolve().then(handler) not call handler immediately?

Promise handlers are placed in the microtask queue and execute after the current JavaScript stack becomes empty. The queue is FIFO, so handlers already queued run before handlers added later.

Follow-up: What happens if a microtask queues another microtask? The newly queued microtask runs after microtasks already waiting, but before the event loop proceeds to another macrotask.

QHow are promise handlers ordered relative to setTimeout callbacks?

The synchronous part of the script runs first. After it finishes, the engine drains the microtask queue before processing timers or other macrotasks, so promise output appears before setTimeout output.

Follow-up: Would rendering occur between two promise handlers? Normally no: the microtask queue is drained before rendering or another macrotask is processed.

QWhy does each handler in a promise chain run in a separate asynchronous step?

In a chain, each then returns a new promise. A handler's returned value settles that new promise, allowing the next handler to be queued with that value once the preceding step completes.

Follow-up: What if a handler returns a pending promise? The next handler waits until that returned promise settles, then receives its fulfillment value or rejection.

  • Promise
  • then
  • catch
  • finally
  • queueMicrotask
  • event loop
  • macrotask

Source: Microtasks. Checked 2026-10-15.