EvolCode
треки/С нуля·10 / 11
7 мин чтения

Async/await — код который ждёт

Когда твой код шлёт запрос к API — ответ приходит через 100-500мс. JavaScript на это время не «зависает» — он умеет ждать асинхронно. Async/await — современный синтаксис для работы с этим. Без него непонятна почти ни одна функция в AI-коде, которая обращается к серверу.

Promise — обещание результата

Promise — это «коробочка», в которой когда-нибудь появится значение (или ошибка). Когда вызываешь fetch(url) — он СРАЗУ возвращает Promise, не данные. Внутри Promise может быть три состояния: pending (ещё ждём), fulfilled (готово), rejected (ошибка). Тебе нужно «открыть» Promise когда он будет готов.

await — «подожди и дай результат»

$ const data = await fetch(url)

JS ставит код на паузу пока Promise не станет готов, потом записывает значение в переменную. Внешне похоже на синхронный код, но JS под капотом не блокирует ничего — другие задачи продолжают идти. await работает ТОЛЬКО внутри функции, помеченной async. Без async — синтаксическая ошибка.

async function

Префикс async перед функцией: 1) разрешает использовать await внутри, 2) автоматически оборачивает возвращаемое значение в Promise. То есть

$ async function f() { return 42 }

возвращает Promise<number>, а не number. Чтобы вызвать другую async-функцию из обычной — либо тоже сделать её async, либо использовать .then().

try/catch для ошибок

Если запрос провалился (нет интернета, 500 от сервера) — Promise отклоняется, и await БРОСАЕТ ошибку. Ловим обычным try/catch:

$ try { const r = await fetch(...) } catch (e) { ... }

Без try/catch ошибка «всплывёт» до вызывающей функции и так далее. Игнорировать нельзя — иначе невидимый сбой.

Параллельно vs последовательно

$ const a = await load1(); const b = await load2();

запросы идут друг за другом (1.5с + 1.5с = 3с). Если они независимы — гоняй параллельно:

$ const [a, b] = await Promise.all([load1(), load2()])

стартуют одновременно (≈ 1.5с). Это частая оптимизация, ИИ её не всегда применяет — можешь сам.

примерjavascript
// === БАЗОВЫЙ ВАРИАНТ ===
async function getUser(id) {
  const r = await fetch(`/api/users/${id}`);
  if (!r.ok) throw new Error(`HTTP ${r.status}`);
  const data = await r.json();        // .json() тоже Promise!
  return data;
}

// Использование
try {
  const user = await getUser(42);
  console.log(user.name);
} catch (e) {
  console.error('Не удалось:', e.message);
}

// === ПОСЛЕДОВАТЕЛЬНО vs ПАРАЛЛЕЛЬНО ===

// ПЛОХО — последовательно, медленно
async function loadDashboardSlow() {
  const user = await fetch('/api/me').then(r => r.json());      // 200мс
  const orders = await fetch('/api/orders').then(r => r.json()); // ждём 200
  const news = await fetch('/api/news').then(r => r.json());     // ждём 200
  return { user, orders, news };
  // Итого: 600мс
}

// ХОРОШО — параллельно
async function loadDashboardFast() {
  const [user, orders, news] = await Promise.all([
    fetch('/api/me').then(r => r.json()),
    fetch('/api/orders').then(r => r.json()),
    fetch('/api/news').then(r => r.json()),
  ]);
  return { user, orders, news };
  // Итого: 200мс — все три стартуют одновременно
}

// === ОБРАБОТКА В ЦИКЛЕ ===

// for-of с await — последовательно (когда нужна очерёдность)
for (const id of ids) {
  await processOne(id);              // ждём каждый перед следующим
}

// Promise.all с .map — параллельно (когда независимы)
await Promise.all(ids.map(id => processOne(id)));

// === ИИ часто пишет так — узнавай ===

async function safeRequest(url) {
  try {
    const r = await fetch(url);
    if (!r.ok) return null;          // или throw — выбор стиля
    return await r.json();
  } catch (e) {
    console.error(e);
    return null;
  }
}

Типичные паттерны async/await — есть и хорошие, и неоптимальные

главное
  • 01fetch и аналоги возвращают Promise — обещание значения позже
  • 02await — «подожди и дай результат», работает ТОЛЬКО в async-функции
  • 03async-функция всегда возвращает Promise — оборачивает результат
  • 04try/catch ловит ошибки от await — без него ошибки «всплывают» дальше
  • 05r.json() ТОЖЕ Promise — нужен второй await
  • 06Promise.all([...]) — параллельно, когда запросы независимы → быстрее в N раз
  • 07for-of с await — последовательно, .map с Promise.all — параллельно
проверь себя
01Что вернёт `async function f() { return 42 }` при вызове `f()`?
02У вас 3 независимых запроса. Какой код быстрее?
03Где можно писать await?
следующий урок: Ошибки — try/catch без боли