JavaScript
async-await
asynchronous programming
programming concepts
function definition

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.

Browse interview questions

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.

javascript
1function plainValue() {
2  return 42;
3}
4
5async function promisedValue() {
6  return 42;
7}
8
9console.log(plainValue());
10promisedValue().then(console.log);

Output:

text
42
42

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:

javascript
1async function fetchName() {
2  const response = await fetch("https://example.com/api/user");
3  const data = await response.json();
4  return data.name;
5}

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:

javascript
1function fetchName() {
2  const response = await fetch("https://example.com/api/user");
3  return response;
4}

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.

javascript
const response = await fetch("https://example.com/config.json");
const config = await response.json();
console.log(config);

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

  • 'await requires async because it introduces function suspension and resumption.'
  • 'async tells 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 await exists in ES modules, but that is a special case rather than a general exception.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track 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.

Browse interview questions

All Rights Reserved.