Where does async and await end? Confusion
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
A lot of confusion around async and await comes from treating them as if they create a separate execution world. They do not. An async function is still ordinary JavaScript code that runs synchronously until it reaches an await, at which point it pauses and returns control to the event loop.
What async Actually Means
When you mark a function async, JavaScript guarantees one thing: the function returns a Promise. Even if you return 42, the caller receives a fulfilled promise whose value is 42.
That means async changes the function's contract at the call site. The caller must use await or .then() to consume the result.
Where await Pauses Execution
Inside an async function, code runs normally until JavaScript hits an await expression. At that moment:
- the awaited value is converted to a promise if needed
- the current function pauses
- the rest of the function is scheduled to resume later
- other JavaScript can continue running
A useful mental model is that await splits one function into two phases: the part before suspension and the continuation after the promise settles.
The output order is:
- '
before call' - '
start' - '
after call' - '
after await'
That ordering explains most of the confusion. The function starts immediately, pauses at await, and finishes later.
Where The Async Work Ends
The async portion of an async function ends when the returned promise settles. That can happen in two ways:
- the function finishes normally and resolves with a value
- an uncaught error is thrown and the promise rejects
Even though JSON.parse itself is synchronous, the outer function still returns a promise. So the boundary is about the function contract, not whether every line inside it is slow or asynchronous.
await Does Not Create Parallelism
Another common misconception is that multiple await calls automatically run concurrently. They do not if written sequentially.
That waits twice in sequence. If you want overlap, start both promises first.
This is often where developers think async somehow "ended too early" or "blocked too long". In reality, the structure of the code decides whether work is serialized.
Error Boundaries
Errors also define where the async flow ends. A thrown error after an await rejects the promise just as surely as a thrown error before it.
The try and catch boundary is the practical end of the async chain for the caller.
How To Think About It Clearly
A reliable rule is:
- '
asyncaffects what the function returns' - '
awaitaffects where that function pauses and resumes'
Nothing magical happens outside those boundaries. JavaScript still has one event loop thread for ordinary code execution, and await simply allows continuation after a promise settles.
Common Pitfalls
The first mistake is assuming that calling an async function means all of its code runs later. The function starts immediately and runs until the first await.
Another issue is forgetting that an async function always returns a promise. Using its return value like a plain synchronous value leads to bugs.
Developers also commonly write several await expressions in a row when the tasks could run concurrently. That is not a bug in await; it is a sequencing choice in the code.
Finally, be careful with error handling. A rejected promise and a thrown exception inside an async function are part of the same promise-based control flow, so callers must still handle rejection properly.
Summary
- An
asyncfunction returns aPromiseimmediately, even if part of its body runs synchronously first. - Code runs normally until an
awaitis reached. - '
awaitpauses the currentasyncfunction and resumes it after the promise settles.' - The async work ends when the function's returned promise resolves or rejects.
- Sequential
awaitcalls serialize work unless you explicitly start promises first and coordinate them withPromise.all.
Related reading
- Where is Peterson's algorithm used in the real world?
- Where to places fences/memory barriers to guarantee a fresh read/committed writes?
- Which Android Priority Job Queue Asynk Task, Multithreading library would you recommend for Android?
- Which browsers support script asyncasync /?
- Where does npm install packages?
- Where is array's length property defined?
- Which concurrent Queue implementation should I use in Java?
- Which io_context does stdboostasiopost / dispatch use?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.