How It Runs

Prefer reading? The full explanation

How await Runs

async / await · Browser

async function main() {
  console.log('1: Main Start');
  await showMessage();
  console.log('2: Main End');
}

async function showMessage() {
  console.log('3: Show Message');
}

console.log('4: Script Start');
main();
console.log('5: Script End');

Output: 4: Script Start → 1: Main Start → 3: Show Message → 5: Script End → 2: Main End

Why does 5 print before 2?

The output is 4 → 1 → 3 → 5 → 2. The two common wrong answers map to two different misconceptions. Expecting 2: Main End before 5: Script End means treating await as something that blocks the whole thread. Expecting 5 before 1 means assuming an async function defers its body the way setTimeout defers a callback. Neither matches what the engine does.

Async functions run synchronously until the first await

Calling main() executes its body immediately, on the current call stack, the same as any other function call. Execution continues until the first await, which is why 1: Main Start and 3: Show Message print before anything is deferred. The async keyword changes the return type to a promise; it does not postpone the body.

showMessage() contains no await at all, so it runs straight through and returns an already-resolved promise.

await suspends the function and queues a microtask

At await showMessage(), the engine suspends main(). Its frame leaves the call stack, and the code after the await (here, console.log("2: Main End")) is packaged into a continuation that goes into the microtask queue.

The thread does not wait around. Control returns to the global script, which prints 5: Script End and finishes. With the stack empty, the event loop drains the microtask queue, main() resumes, and 2: Main End prints last.

The continuation has no special priority. It queues in FIFO order next to every other microtask, which the experiment above demonstrates against an explicit Promise.then. One detail worth knowing when you read older material: since V8 7.2 (Chrome 73, Node 12), awaiting a native promise resumes in a single microtask tick, while earlier engines took three, so pre-2019 articles report different orderings for more elaborate snippets.

Reading about it is one thing. Watching it run is another.

↑ Run it step by step