async function

Объявление async function определяет асинхронную функцию, которая возвращает объект AsyncFunction.

Вы также можете определить async-функции, используя выражение async function.

Синтаксис

async function name([param[, param[, ... param]]]) {
   statements
}
name

Имя функции.

param

Имя аргумента, который будет передан в функцию.

statements

Выражение, содержащее тело функции.

Описание

После вызова функция async возвращает Promise. Когда результат был получен, Promise завершается, возвращая полученное значение. Когда функция async выбрасывает исключение, Promise ответит отказом с выброшенным (throws) значением.

Функция async может содержать выражение await, которое приостанавливает выполнение функции async и ожидает ответа от переданного Promise, затем возобновляя выполнение функции async и возвращая полученное значение.

Ключевое слово await допустимо только в асинхронных функциях. В другом контексте вы получите ошибку SyntaxError.

Примечание: Цель функций async/await упростить использование promises синхронно и воспроизвести некоторое действие над группой Promises. Точно так же как Promises подобны структурированным колбэкам, async/await подобна комбинации генераторов и promises.

Примеры

Простой пример

js

function resolveAfter2Seconds(x) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

async function add1(x) {
  const a = await resolveAfter2Seconds(20);
  const b = await resolveAfter2Seconds(30);
  return x + a + b;
}

add1(10).then((v) => {
  console.log(v); // prints 60 after 4 seconds.
});

async function add2(x) {
  const a = resolveAfter2Seconds(20);
  const b = resolveAfter2Seconds(30);
  return x + (await a) + (await b);
}

add2(10).then((v) => {
  console.log(v); // prints 60 after 2 seconds.
});

Предупреждение: #### Не путайте await и Promise.allФункция add1 приостанавливается на 2 секунды для первого await и ещё на 2 для второго. Второй таймер создаётся только после срабатывания первого. В функции add2 создаются оба и оба же переходят в состояние await. В результате функция add2 завершится скорее через две, чем через четыре секунды, поскольку таймеры работают одновременно. Однако запускаются они всё же не параллельно, а друг за другом - такая конструкция не означает автоматического использования Promise.all. Если два или более Promise должны разрешаться параллельно, следует использовать Promise.all.

Когда функция async выбрасывает исключение

js

async function throwsValue() {
  throw new Error("oops");
}
throwsValue().then(
  (resolve) => {
    console.log("resolve:" + resolve);
  },
  (reject) => {
    console.log("reject:" + reject);
  },
);
//prints "reject:Error: oops"
//or
throwsValue()
  .then((resolve) => {
    console.log("resolve:" + resolve);
  })
  .catch((reject) => {
    console.log("reject:" + reject);
  });
//prints "reject:Error: oops"

Перепись цепочки promise с использованием функции async

API, которое возвращает Promise, будет возвращать значение в цепочке, тем самым разбивая функцию на много частей. Рассматривая следующий код:

js

function getProcessedData(url) {
  return downloadData(url) // returns a promise
    .catch((e) => {
      return downloadFallbackData(url); // returns a promise
    })
    .then((v) => {
      return processDataInWorker(v); // returns a promise
    });
}

он может быть переписан с одним использованием функции async:

js

async function getProcessedData(url) {
  let v;
  try {
    v = await downloadData(url);
  } catch (e) {
    v = await downloadFallbackData(url);
  }
  return processDataInWorker(v);
}

Заметьте, что пример выше не содержит await на return, потому что возвращаемое значение функции async неявно обёрнуто в Promise.resolve.

Спецификации

Specification
ECMAScript Language Specification
# sec-async-function-definitions

Поддержка браузерами

BCD tables only load in the browser

Смотрите также