Skip to main content

Why await pauses only the current function

await does not block the JavaScript execution thread, it suspends only the async function it sits in. The rest of the program, event handlers, timers and other async functions keep running, because await hands control back to the Event Loop.

Theory

TL;DR

  • JavaScript runs code on a single thread but schedules work through the Event Loop queues.
  • await does not stop that thread, it freezes only the current async function.
  • The engine wraps the rest of the function body into a microtask that runs once the promise settles.
  • The call stack is cleared, so other code (timers, events, other functions) keeps executing.
  • When the promise becomes fulfilled or rejected, the function continues exactly at the await line.
  • This is an asynchronous pause, not a block: no OS threads and no sleep are involved.

Quick example

javascript
async function task() { console.log('Start'); await new Promise(r => setTimeout(r, 2000)); console.log('End'); } task(); // This line runs immediately, the engine is not blocked console.log('This code runs right away!');

Output:

text
Start This code runs right away! (after 2 s) End

await suspends only the task() function, while the main code moves on. JS does not freeze: inside task() the engine simply creates a microtask that returns to the queue after the timer fires.

What happens under the hood

When the engine meets await promise, this is what it does:

  1. It suspends the execution of the current async function.
  2. It creates a microtask (a callback) that will continue the function once the promise settles.
  3. It returns control to the Event Loop and clears the call stack.
  4. The engine runs other work: other functions, event handlers, timers and so on.
  5. When the promise settles (fulfilled or rejected), the microtask runs and the function resumes at the exact line where await stood.

All of this is implemented through the microtask queue (PromiseJobs). The engine uses no extra threads and no real sleep.

Step by step in the Event Loop

StageWhat happens
1task() enters the Call Stack and runs the code up to await
2At await the function is frozen and a microtask is created
3The stack is cleared, other scripts keep executing
4When the promise settles, the microtask goes back into the queue
5After the current Event Loop tick, the remaining code of task() runs

If await really blocked the thread, the whole of JavaScript would hang for those 2 seconds: not a single event handler and not a single setTimeout would fire. That does not happen: while task() waits, the Event Loop calmly processes other events.

Parallel async functions do not wait for each other

javascript
async function foo() { console.log('foo start'); await new Promise(res => setTimeout(res, 1000)); console.log('foo end'); } async function bar() { console.log('bar start'); await new Promise(res => setTimeout(res, 500)); console.log('bar end'); } foo(); bar(); console.log('main thread');

Output:

text
foo start bar start main thread (after 0.5 s) bar end (after 1 s) foo end

await does not get in the way of other functions. Each function simply freezes until its own promise settles and then continues independently of its neighbour.

The resumption microtask and the order of output

javascript
async function demo() { console.log('A'); await Promise.resolve(); console.log('B'); } demo(); console.log('C');

Result:

text
A C B

Why exactly this order:

  • A runs synchronously, before await;
  • await stops the function and puts its continuation (B) into the microtask queue;
  • the main code reaches C;
  • and only when the stack is empty does the engine run the microtasks, that is, B.

A simple analogy: an async function is like a TV series. At await that particular series is paused, but the other channels keep broadcasting. When the promise it waits for is ready, the episode continues from the exact frame where it stopped.

What await does and does not do

What await doesWhat it does not do
Suspends only the current async functionDoes not block the JavaScript thread
Returns control to the Event LoopDoes not prevent other tasks from running
Resumes execution once the promise settlesDoes not freeze the whole application
Is implemented through microtasks (PromiseJobs)Does not use OS threads or sleep

Common mistakes

  • Believing that await stops the whole page, and therefore avoiding it in code that reacts to events.
  • Confusing a suspended function with a blocked thread: a real block is a synchronous loop such as while (Date.now() < end) {}, and that is what freezes the tab, because it never gives the stack back.
  • Putting await inside a loop where the requests are independent: the function waits for them one by one, although they could all start together with Promise.all().
  • Expecting two consecutive await statements to run in parallel. They are strictly sequential: the second starts only after the first has settled.
  • Forgetting that after await the code continues inside a microtask, so the log order differs from a top to bottom synchronous reading.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.