Output Quiz #6 — Promises & async/await Ordering

10 output questions on Promise executor timing, .then() as microtasks, async return values, await suspension, and unhandled rejections.

10 min read
JavaScript
Interview
Output

TABLE OF CONTENTS
Output Quiz #6 — Promises & async/await Ordering

Promises and async/await are the most common source of output-ordering surprises in modern JavaScript interviews. The key insight: Promise callbacks are microtasks, and await is syntactic sugar for .then(). Ten questions to cement that model.


Q1 — Promise executor is synchronous

Loading editor...

Show answer

Output:

before
executor
after

Why: The Promise executor function runs synchronously at the point the Promise is constructed. "executor" logs between "before" and "after". The resolved value "done" goes nowhere here because there's no .then() — but the executor itself is not async.


Q2 — .then() is a microtask

Loading editor...

Show answer

Output:

A
C
B

Why: .then() callbacks are scheduled as microtasks — they don't run until the current synchronous execution completes. "A" and "C" run synchronously; only after the call stack is empty does the microtask "B" run.


Q3 — Returning a value from .then()

Loading editor...

Show answer

Output:

4

Why: Each .then() receives the return value of the previous handler. 1 + 1 = 2, then 2 * 2 = 4, then 4 is logged. Returning a non-Promise value from .then() wraps it in a resolved Promise for the next handler.


Q4 — async function return value

Loading editor...

Show answer

Output:

true
42

Why: An async function always returns a Promise, even if you return a plain value. getValue() returns Promise.resolve(42). So result instanceof Promise is true. The .then() callback receives 42 as a microtask.


Q5 — await pauses, then resumes

Loading editor...

Show answer

Output:

1
4
2
3

Why: main() runs synchronously until await. 1 logs. The await suspends main() and schedules the rest as a microtask, returning control to the caller. 4 logs synchronously. Then the microtask resumes: val is 2, 2 and 3 log.


Q6 — Promise.all ordering

Loading editor...

Show answer

Output:

sync
first second

Why: "sync" runs before the await resolves (microtask). Promise.all resolves when all input Promises resolve — since both are already resolved, it resolves immediately. The destructured values maintain input order regardless of resolution order: a = "first", b = "second".


Q7 — Rejected Promise and .catch()

Loading editor...

Show answer

Output:

catch: error
after catch

Why: A rejection skips all .then() handlers until it finds a .catch() (or a .then(null, onReject) handler). The .then after .catch runs because .catch returned a resolved Promise (it didn't re-throw). The chain is back to the resolved track after the .catch.


Q8 — try/catch with async/await

Loading editor...

Show answer

Output:

caught: oops
done

Why: await on a rejected Promise throws at the await expression — which the surrounding try/catch can intercept. "never" is unreachable. After the catch block handles the error, execution continues normally, so "done" logs.


Q9 — Promise.all vs sequential await

Loading editor...

Show answer

Output:

sync
a b
a b

Why: Both sequential() and parallel() suspend at await, so "sync" logs first. For these already-resolved Promises, timing is similar — but in real code with delays, parallel() would resolve faster because both Promises run concurrently. The logged output is the same (a b twice) because the values are the same; the order between the two functions depends on microtask scheduling. sequential has two awaits (two microtask checkpoints), parallel has one, so parallel's .then is scheduled one microtask later — but with resolved promises they interleave such that both log on the same microtask "beat."


Q10 — Unhandled rejection

Loading editor...

Show answer

Output:

after fail()
(UnhandledPromiseRejection warning in Node / unhandledrejection event in browser)

Why: fail() returns a rejected Promise (because async functions convert thrown errors into rejections). The rejection is not handled (no .catch(), no await inside a try/catch). "after fail()" logs synchronously before the rejection is processed. Node.js emits an UnhandledPromiseRejection warning; browsers fire the unhandledrejection event. The key point: an unhandled rejection inside an async function is silent until the engine checks for it.


Key Rules

PatternBehaviour
Promise executorRuns synchronously
.then() / .catch()Scheduled as microtasks — run after current sync code
async functionAlways returns a Promise
await exprSuspends the function; the rest runs as a microtask
Returned value from .then()Wrapped in a resolved Promise for the next handler
Thrown error / rejected awaitJumps to nearest .catch() or try/catch
Promise.allResolves when all resolve; preserves input order

Go Deeper


Let's Connect

© 2026 Naveen Karthik // Built with React & MUI