Why 'await' requires 'async' in function definition
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
JavaScript does not allow await in an ordinary function because await changes how the function executes and what it returns. Marking the function async tells the language runtime that the body may pause at suspension points and that the function result must be wrapped in a promise.
What await Actually Does
await is not just syntax sugar for “wait here.” It splits the function into two phases:
- run until the awaited promise is reached
- pause that function and resume it later when the promise settles
That pause changes the control flow. A normal synchronous function has no protocol for suspending itself and then continuing later. An async function does.
This is why JavaScript needs the async marker up front. It is a contract with the runtime and with anyone calling the function.
async Changes the Return Type
A normal function returns a plain value immediately. An async function always returns a promise, even if you write a simple return 42.
Output:
The values look similar, but the second one arrives through a promise. That is exactly the behavior await depends on. If await were allowed in a non-async function, the language would need another rule for what that function returns and how callers should handle the pause.
A Simple Example
This is valid JavaScript:
Because the function is marked async, JavaScript knows it may suspend at each await and later resume when the promise settles.
This is invalid inside a regular function:
The parser rejects it because ordinary functions do not support that suspension model.
Why the Restriction Helps
Requiring async makes asynchronous behavior explicit. When you read a function signature, you can immediately infer two things:
- the function may pause internally
- the caller will receive a promise
That explicitness matters for readability and correctness. Without it, a function that looks synchronous could suddenly return asynchronously, which would make code much harder to reason about.
The rule also protects existing JavaScript semantics. Ordinary functions have long been expected to run straight through and return a value right away. async preserves that distinction instead of overloading every function form with hidden suspension behavior.
The Important Exception: Top-Level await
Modern JavaScript does allow await outside a named async function in one special case: top-level await inside ES modules.
Even here, the surrounding module is treated specially by the JavaScript module system. This is not the same as allowing await in any random function body.
Common Pitfalls
The most common mistake is thinking await blocks the whole program like a synchronous sleep. It does not. It pauses only the surrounding async function while the event loop can continue processing other work.
Another mistake is forgetting that an async function always returns a promise. If you call it from non-async code, you still need to use .then(...) or otherwise handle the promise.
It is also easy to confuse await support in top-level modules with support inside ordinary functions. They are different rules in the language.
Summary
- '
awaitrequiresasyncbecause it introduces function suspension and resumption.' - '
asynctells JavaScript that the function returns a promise.' - Ordinary functions do not have the runtime contract needed for
await. - The rule makes asynchronous behavior explicit and easier to reason about.
- Top-level
awaitexists in ES modules, but that is a special case rather than a general exception.
Related reading
- Why can GPU do matrix multiplication faster than CPU?
- Why can I not throw inside a Promise.catch handler?
- Why CancellationToken is separate from CancellationTokenSource?
- Why CancellationTokenSource hangs an application
- Why chrome console is not returning undefined here?
- Why do my vue-router links sporadically lead to the wrong page or don't work at all?
- Why can't asynchronous threads modify an ArrayList simultaneously?
- Why can't I use the 'await' operator within the body of a lock statement?
.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.