Что такое async/await в JavaScript?

JuniorJavaScript · Frontend·Обновлено 20 июня 2026
Коротко
async/await — это синтаксический сахар над промисами, позволяющий писать асинхронный код в синхронном стиле. Функция, помеченная async, всегда возвращает Promise, а await приостанавливает её выполнение до разрешения промиса.

Что такое async/await

async/await — это синтаксическая конструкция, появившаяся в ECMAScript 2017 (ES8), которая упрощает работу с промисами. По сути это «обёртка» над Promise API, позволяющая писать асинхронный код так, будто он выполняется последовательно и синхронно. При этом цикл событий не блокируется, а сам код становится гораздо читабельнее, чем цепочки .then().

Ключевое слово async

Ключевое слово async ставится перед объявлением функции и делает её асинхронной. Такая функция всегда возвращает Promise, даже если внутри явно вернуть обычное значение — оно будет автоматически обёрнуто в Promise.resolve(). Если внутри async-функции выбрасывается исключение, возвращённый промис переходит в состояние rejected.

async function getNumber() {
  return 42; // вернётся Promise<42>
}

getNumber().then(value => console.log(value)); // 42

Ключевое слово await

Ключевое слово await можно использовать только внутри async-функций (или на верхнем уровне ES-модулей — top-level await). Оно «приостанавливает» выполнение функции до тех пор, пока промис не будет разрешён, и возвращает его результат. Если промис отклоняется, await пробрасывает ошибку, которую можно поймать через try/catch.

async function loadUser(id) {
  // приостанавливаем выполнение до получения ответа
  const response = await fetch(`/api/users/${id}`);
  const user = await response.json();
  return user;
}

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

Для обработки ошибок в async/await используется привычный механизм try/catch, что делает код единообразным с синхронным. Это одно из главных преимуществ перед .catch() у промисов.

async function safeLoad() {
  try {
    const data = await fetch('/api/data');
    return await data.json();
  } catch (error) {
    // ловим и сетевые ошибки, и ошибки парсинга JSON
    console.error('Ошибка загрузки:', error);
    return null;
  }
}

Параллельное выполнение

Последовательные await-вызовы выполняются один за другим, что может замедлить код. Для параллельного запуска независимых операций используйте Promise.all совместно с await.

// плохо: запросы идут последовательно (~2 секунды)
const user = await fetchUser();
const posts = await fetchPosts();

// хорошо: запросы идут параллельно (~1 секунда)
const [user, posts] = await Promise.all([
  fetchUser(),
  fetchPosts(),
]);

Связь с промисами

Важно понимать, что async/await не заменяет промисы, а работает поверх них. Любую async-функцию можно переписать через .then(), и наоборот. Под капотом движок превращает async-функцию в конечный автомат, который продолжает работу при разрешении промиса в микрозадаче.

Что хочет услышать интервьюер

Понимание, что async-функция всегда возвращает Promise

Знание, что await работает только внутри async-функций (или на top-level в модулях)

Умение обрабатывать ошибки через try/catch

Понимание разницы между последовательным и параллельным выполнением (Promise.all)

Осознание, что async/await — это синтаксический сахар над промисами, а не замена им

Пример: Базовый пример async/await с обработкой ошибок

interface User {
  id: number;
  name: string;
}

async function fetchUser(id: number): Promise<User | null> {
  try {
    const response = await fetch(`/api/users/${id}`);

    if (!response.ok) {
      throw new Error(`HTTP error: ${response.status}`);
    }

    // ждём парсинга JSON
    const user: User = await response.json();
    return user;
  } catch (error) {
    console.error('Не удалось загрузить пользователя:', error);
    return null;
  }
}

// использование
const user = await fetchUser(1);

Пример: Параллельное выполнение через Promise.all

async function loadDashboard(userId: number) {
  // все три запроса стартуют одновременно
  const [user, posts, comments] = await Promise.all([
    fetch(`/api/users/${userId}`).then(r => r.json()),
    fetch(`/api/users/${userId}/posts`).then(r => r.json()),
    fetch(`/api/users/${userId}/comments`).then(r => r.json()),
  ]);

  return { user, posts, comments };
}

Типичные ошибки

Использование await вне async-функции, что приводит к синтаксической ошибке

Последовательные await для независимых операций вместо Promise.all — потеря производительности

Забывают про try/catch и теряют ошибки в виде unhandled promise rejection

Думают, что async/await делает код синхронным и блокирует поток

Использование await в forEach — он не дожидается завершения промисов; нужен for...of или Promise.all с map

Лучшие курсы по теме

изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Feature-Sliced Design

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.5
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее