04. Async Function Execution

This is how async functions are executed:

  • The result of an async function is always a Promise p. That Promise is created when starting the execution of the async function.

  • The body is executed.

    • Execution may finish permanently via return or throw.

    • Or it may finish temporarily via await; in which case execution will usually continue later on.

  • The Promise p is returned.

While executing the body of the async function, return x resolves the Promise p with x, while throw err rejects p with err. Therefore, you can return a Promise and that Promise won’t be wrapped in a Promise. Intriguingly, returning a rejected Promise leads to the result of the async function being rejected (normally, you’d use throw for that).

It enables you to forward both fulfillments and rejections of another asynchronous computation, without an await:

async function asyncFunc() {
  return anotherAsyncFunc();
}

Event ordering

Async functions are started synchronously, settled asynchronously. The notification of a settlement happens asynchronously. In other words:

  • async-функция выполняется синхронно c основным потоком до первого await выражения;

  • Выполнение асинхронной функции между await вызовами происходит асинхронно.

  • the callbacks of then() and catch() are always executed after the current code is finished.

async function asyncFunc() {
  console.log("asyncFunc()"); // (A)
  return "abc";
}

asyncFunc().then(x => console.log(`Resolved: ${x}`)); // (B)
console.log("main"); // (C)

// Output:
// asyncFunc()
// main
// Resolved: abc

Выполнение async/await функций не блокирует основной поток выполнения.

Async functions and Promises

Особенности:

  • Async функции позволяют писать синхронно выглядящий код при его асинхронном выполнении.

  • Async функции не являются полной альтернативой Promise.

Фундаментальное отличие между асинхронными функциями и нативными Promise в том, что await X() приостанавливает выполнение текущей функции, тогда как promise.then(X) продолжает выполнение после добавления вызова X в цепочку функций обратного вызова. Для stack trace эта разница весьма значительная.

Last updated