This post explains a quiz originally shared as a LinkedIn poll.
πΉ The Question
console.log('1');
Promise.resolve()
.then(() => {
console.log('2');
return Promise.resolve('3');
})
.then((val) => {
console.log(val);
Promise.resolve('4').then(console.log);
})
.then(() => {
console.log('5');
});
console.log('6');
Hint: Consider the microtask queue and how promise resolution affects the order of execution.
πΉ Solution
Correct Answer: B) 1, 6, 2, 3, 5, 4
The output will be: 1, 6, 2, 3, 5, 4
π§ How this works
This quiz demonstrates a subtle but critical aspect of JavaScript's promise resolution and microtask queue behavior. The key mechanism here is how returning a promise from a .then() handler affects the microtask queue scheduling.
When you return a promise from a .then() handler, JavaScript doesn't immediately schedule the next .then() handler. Instead, it waits for that returned promise to resolve, and only then does it schedule the next handler as a new microtask. This creates an additional microtask queue cycle.
The non-obvious part is in the second .then() handler: when we call Promise.resolve('4').then(console.log), we're creating a new promise chain that gets scheduled as a microtask, but this happens after the current promise chain has already scheduled its next handler (console.log('5')).
π Line-by-line explanation
console.log('1')executes immediately β outputs1Promise.resolve()creates a resolved promise and schedules its.then()handler as a microtaskconsole.log('6')executes immediately (synchronous code runs first) β outputs6-
Microtask queue processing begins:
- First
.then()handler executes:console.log('2')β outputs2 - Returns
Promise.resolve('3')- this is the critical part
- First
Promise resolution behavior: When a
.then()handler returns a promise, JavaScript waits for that promise to resolve before scheduling the next handler. SincePromise.resolve('3')is already resolved, it schedules the next.then()handler as a new microtask (not in the current microtask queue cycle)-
Current microtask queue cycle completes, then the next cycle begins:
- Second
.then()handler executes: receives'3', outputs3 - Creates
Promise.resolve('4').then(console.log)- this schedules a new microtask - Returns
undefined(implicit return)
- Second
-
Third
.then()handler is scheduled as a microtask (because the previous handler returnedundefined, not a promise, so it's scheduled immediately in the same cycle):- Executes:
console.log('5')β outputs5
- Executes:
-
Next microtask queue cycle:
- The
Promise.resolve('4').then(console.log)microtask executes β outputs4
- The
The misleading part: Many developers expect 4 to appear before 5 because it's created earlier in the code. However, because the second .then() handler returns undefined (not a promise), the third .then() handler gets scheduled in the same microtask cycle, while the Promise.resolve('4') chain gets scheduled for the next cycle.
πΉ Key Takeaways
-
Returning a promise from
.then()adds an extra microtask cycle: When a.then()handler returns a promise, JavaScript waits for that promise to resolve before scheduling the next handler, creating a new microtask queue cycle.
Follow me for JavaScript puzzles and weekly curations of developer talks & insights at Talk::Overflow: https://talkoverflow.substack.com/
Microtask queue processing is atomic per cycle: All microtasks scheduled in the current cycle execute before the next cycle begins, but promises returned from handlers create new cycles.
Nested promise chains schedule independently: When you create a new promise chain inside a
.then()handler (likePromise.resolve('4').then(...)), it gets scheduled for a future microtask cycle, not the current one.Return value matters: Returning
undefinedvs. returning a promise from a.then()handler affects when the next handler is scheduled -undefinedschedules immediately in the current cycle, while a promise waits for resolution.This is why
async/awaitcan be clearer: Usingasync/awaitmakes the execution order more explicit and easier to reason about, though the underlying microtask behavior remains the same.
Follow me for JavaScript puzzles and weekly curations of developer talks & insights at Talk::Overflow: https://talkoverflow.substack.com/
Top comments (0)