Tools
Tools: Javascript Question of the Day #13 [Talk::Overflow]
2026-02-08
0 views
admin
πΉ The Question ## πΉ Solution ## π§ How this works ## π Line-by-line explanation ## πΉ Key Takeaways This post explains a quiz originally shared as a LinkedIn poll. Hint: Think about when await actually pauses execution and what runs synchronously before the first suspension point in each function. Correct Answer: A) 5, 1, 3, 6, 4, 2 The output is: 5, 1, 3, 6, 4, 2 This quiz tests a fundamental misunderstanding about async/await: an async function runs synchronously up until its first await expression. The await keyword is the suspension point β everything before it executes immediately on the call stack, just like regular synchronous code. When await encounters a resolved or pending Promise, it doesn't block the thread. Instead, it schedules the rest of the function (the continuation) as a microtask and returns control to the caller. The caller then continues executing synchronously. The critical insight is that await on an already-resolved Promise (like Promise.resolve()) still causes a suspension. It doesn't short-circuit. The continuation is placed on the microtask queue and executes after the current synchronous call stack completes. With nested async functions, this creates a chain: second() suspends first, and when it resumes and completes, only then does first() resume β each resumption happening in a separate microtask. console.log(5) β synchronous, runs immediately. Output: 5 first() is called β enters the async function synchronously Inside first: console.log(1) β still synchronous (before the first await). Output: 1 Inside first: await second() β calls second() synchronously before awaiting its result Inside second: console.log(3) β still synchronous (before second's first await). Output: 3 Inside second: await Promise.resolve() β this is the first real suspension point: Back in first: await second() β the Promise from second() is still pending (second hasn't finished), so first() is also suspended. Control returns to the top-level caller. console.log(6) β synchronous code in the top-level script. Output: 6 Synchronous call stack is empty. Microtask queue processes: Microtask 1: Resume second() β console.log(4) runs. Output: 4. second() completes, and its Promise resolves. This resolution schedules another microtask to resume first(). Microtask 2: Resume first() β console.log(2) runs. Output: 2 The misleading part: Many developers expect await on an already-resolved Promise to continue synchronously (like an immediate return), producing 5, 1, 3, 4, 2, 6. But the spec requires that await always yields at least once, even for resolved Promises. This is by design β it ensures consistent, predictable scheduling regardless of whether a Promise was pre-resolved or will resolve later. Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse CODE_BLOCK:
async function first() { console.log(1); await second(); console.log(2);
} async function second() { console.log(3); await Promise.resolve(); console.log(4);
} console.log(5);
first();
console.log(6); Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
async function first() { console.log(1); await second(); console.log(2);
} async function second() { console.log(3); await Promise.resolve(); console.log(4);
} console.log(5);
first();
console.log(6); CODE_BLOCK:
async function first() { console.log(1); await second(); console.log(2);
} async function second() { console.log(3); await Promise.resolve(); console.log(4);
} console.log(5);
first();
console.log(6); - console.log(5) β synchronous, runs immediately. Output: 5
- first() is called β enters the async function synchronously
- Inside first: console.log(1) β still synchronous (before the first await). Output: 1
- Inside first: await second() β calls second() synchronously before awaiting its result
- Inside second: console.log(3) β still synchronous (before second's first await). Output: 3
- Inside second: await Promise.resolve() β this is the first real suspension point: Promise.resolve() creates an already-resolved Promise
But await still suspends second() β it schedules the continuation (console.log(4)) as a microtask second() returns a pending Promise to first()
- Promise.resolve() creates an already-resolved Promise
- But await still suspends second() β it schedules the continuation (console.log(4)) as a microtask
- second() returns a pending Promise to first()
- Back in first: await second() β the Promise from second() is still pending (second hasn't finished), so first() is also suspended. Control returns to the top-level caller.
- console.log(6) β synchronous code in the top-level script. Output: 6
- Synchronous call stack is empty. Microtask queue processes:
- Microtask 1: Resume second() β console.log(4) runs. Output: 4. second() completes, and its Promise resolves. This resolution schedules another microtask to resume first().
- Microtask 2: Resume first() β console.log(2) runs. Output: 2 - Promise.resolve() creates an already-resolved Promise
- But await still suspends second() β it schedules the continuation (console.log(4)) as a microtask
- second() returns a pending Promise to first() - An async function executes synchronously up to its first await β it's not fully asynchronous from the start
- await on an already-resolved Promise still suspends execution β it doesn't continue synchronously
- Each await resumption happens as a separate microtask, which runs after the current synchronous call stack clears
- Nested async functions create a chain of microtasks β each inner resumption must complete before the outer one can resume
- Never assume an async function has completed just because you called it β always await or .then() if you depend on its side effects
- The microtask queue (Promises, queueMicrotask) always drains before the macrotask queue (setTimeout, setInterval, I/O)
how-totutorialguidedev.toaijavascript