Промисы — очень удобный инструмент организации асинхронного кода. Но мозгу человека намного привычнее синхронные операции. Сделали что-то, подождали, потом продолжили.

Await

Для упрощения асинхронных операций в JavaScript придумали ключевое слово await. Если написать его перед функцией, которая возвращает промис, то выполнение программы остановится до тех пор, пока промис не завершится.

const userCount = await getUserCount();

console.log(userCount); // 12345

На экране появится сразу значение с которым завершится промис, который возвращает getUserCount(). А если не написать await, то мы увидим в консоли строку Promise { <pending> }.

Async

Ключевое слово await нельзя использовать в обычной функции. Нужно обязательно сделать ее асинхронной, добавив перед списком параметров функции ключевое слово async.

const logUserCount = async () => {
  const userCount = await getUserCount();
  console.log(userCount);
}

Все асинхронные функции возвращают Promise, даже если внутри них нет await.

const getHelloWorld = async () => {
  return 'Hello, world!';
}

console.log(getHelloWorld); // Promise { <pending> }

А чтобы получить результат промиса, нужно добавить все тот же await. Или убрать async, если ты точно уверен, что функция getHelloWorld будет выполнять только синхронные операции.

const getHelloWorld = async () => {
  return 'Hello, world!';
}

console.log(await getHelloWorld()); // Hello, world!

Обработка ошибок

Ошибка может возникнуть всегда. Особенно в асинхронных операциях. Файл может оказаться недоступен, когда мы пытаемся его прочитать. Или может пропасть интернет, когда мы будет грузить картинку с удаленного сервера.

Ошибки в промисах обрабатываются с помощью .catch():

fetchUserData(userId).then(console.log).catch(handleError);

Но если ты используешь await для ожидания промиса, то ты можешь использовать для обработки ошибок обычный блок try/catch:

try {
  await fetchUserData(userId)
} catch (e) {
  console.log('asynchronous error was caught!');
  handleError(e);
}