Await and Thenable Handling

`await` applies Promise-like resolution to its operand, so it can adopt the state of native promises and thenables rather than simply returning the operand unchanged. The async function resumes asynchronously through the JavaScript microtask mechanism after the awaited value settles.

Inside an `async` function, `await` pauses the function's continuation until the supplied expression has been resolved. The operand is processed using promise-resolution semantics, so an ordinary value is treated as already fulfilled, while a promise or thenable can determine when the continuation proceeds.

A thenable is an object with a callable `then` property. `await` does not require the object to be an actual `Promise`; it can assimilate a compatible thenable and follow the outcome produced through its `then` method.

Even when the operand is already fulfilled or is a non-promise value, the code after `await` does not execute synchronously in the current call stack. The continuation is scheduled through the promise/microtask machinery, which means other currently queued microtasks can affect the exact ordering.

If resolution ultimately produces a rejection, the `await` expression throws that rejection reason inside the async function. A surrounding `try`/`catch` can handle it, or the async function's returned promise becomes rejected if the error escapes.

This distinction matters in frontend code because `await` is both a control-flow feature and a promise-resolution boundary. It makes asynchronous sequencing easier to read, but it does not make the underlying operation synchronous or eliminate microtask scheduling.

Key points

Interview questions

What happens when you `await` a non-Promise value?

The value is handled using promise-resolution semantics, so it behaves as an already-fulfilled result. The async function still does not continue synchronously at that point. Its continuation runs through the microtask mechanism. Therefore, `await 42` eventually produces `42`, but code after the `await` executes asynchronously.

What is a thenable, and why does `await` care about it?

A thenable is an object whose `then` property is callable. Promise resolution can assimilate such objects instead of requiring an actual native `Promise`. When `await` processes a thenable, it follows the outcome communicated through that object's `then` method. This allows promise-like implementations to participate in async control flow.

Does `await` block the JavaScript thread?

No. `await` suspends the current async function rather than blocking the JavaScript thread. The surrounding event loop can continue processing other work while the async function is suspended. Once the awaited operation settles, the function's continuation is scheduled through the microtask mechanism.

What happens if the awaited promise rejects?

The `await` expression throws the rejection reason inside the async function. A surrounding `try`/`catch` can intercept it like a synchronous exception at that point in the function. If the error is not caught, the async function's returned promise becomes rejected. This makes `try`/`catch` a natural way to handle failures around awaited operations.

Why can a thenable behave differently from a native Promise?

A native promise has standardized behavior, while a thenable is arbitrary user-provided object behavior exposed through its `then` method. Promise resolution therefore has to carefully assimilate the thenable and protect against cases such as thrown errors or repeated attempts to settle. The first effective settlement determines the adopted outcome. This is one reason promise-resolution semantics are more involved than simply checking whether an object is an instance of `Promise`.