0Pricing
Frontend Academy · Урок

async/await и обработка ошибок

Пишите асинхронные функции с ключевым словом await, оборачивайте ожидаемые вызовы в блоки try/catch и разбирайтесь, почему async/await — это синтаксический сахар над Promise.

«async/await и обработка ошибок» — бесплатный урок Frontend Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Frontend Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Frontend Academy содержит 4 уроков всего.

Что такое асинхронные функции и ожидание

Асинхронные функции и ожидание — это синтаксический сахар над промисами. Асинхронная функция всегда возвращает промис. Оператор ожидания приостанавливает функцию, пока ожидаемый промис не завершится. Код выглядит синхронным, но выполняется асинхронно.

Асинхронная функция

Добавьте ключевое слово async перед объявлением или выражением функции. Теперь функция неявно оборачивает возвращаемое значение в промис.

async function fetchUser(id) {
  // implicitly returns a Promise
  return { id, name: 'Alice' };
}

// Equivalent to:
function fetchUser(id) {
  return Promise.resolve({ id, name: 'Alice' });
}

await — ожидание промисов

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

async function loadProfile(id) {
  const user = await fetchUser(id);     // waits for Promise
  const posts = await fetchPosts(user.id); // waits again
  return { user, posts };
}

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

Последовательное ожидание легко читать, но оно медленно, если задачи не зависят друг от друга. Используйте Promise.all(), чтобы ожидать несколько независимых задач параллельно.

// Sequential (slow if tasks are independent):
const user = await fetchUser(id);
const settings = await fetchSettings(id); // waits for user unnecessarily

// Parallel (fast):
const [user, settings] = await Promise.all([
  fetchUser(id),
  fetchSettings(id),
]);

Обработка ошибок с помощью try/catch

Заключайте вызовы с ожиданием в конструкцию try/catch, чтобы обрабатывать отклонения. Блок catch получает причину отклонения в виде объекта ошибки.

async function saveUser(data) {
  try {
    const response = await fetch('/api/users', {
      method: 'POST',
      body: JSON.stringify(data),
      headers: { 'Content-Type': 'application/json' }
    });
    if (!response.ok) throw new Error(`Server error ${response.status}`);
    return await response.json();
  } catch (err) {
    console.error('Save failed:', err.message);
    throw err; // re-throw so caller can handle
  }
}

Ожидание на верхнем уровне

В модулях ES (но не в CommonJS) можно использовать await на верхнем уровне, не оборачивая его в асинхронную функцию. Это полезно для инициализации модуля.

// module.js (ES module)
const config = await fetch('/config.json').then(r => r.json());
export const API_URL = config.apiUrl;

Асинхронные функции с forEach — подводный камень

Array.forEach() не ожидает асинхронные функции обратного вызова. Используйте for...of для последовательного асинхронного перебора или Promise.all(arr.map(...)) для параллельного выполнения.

// WRONG — forEach doesn't await:
items.forEach(async (item) => {
  await processItem(item); // runs but forEach doesn't wait
});

// CORRECT — sequential:
for (const item of items) {
  await processItem(item);
}

// CORRECT — parallel:
await Promise.all(items.map(item => processItem(item)));

Объекты ошибок и пользовательские ошибки

Всегда выбрасывайте объекты ошибок, а не строки, чтобы сохранялись трассировки стека. Создавайте пользовательские классы ошибок для ошибок конкретной предметной области, которые вызывающий код может перехватывать по типу.

class NetworkError extends Error {
  constructor(message, status) {
    super(message);
    this.name = 'NetworkError';
    this.status = status;
  }
}

try {
  const res = await fetch(url);
  if (!res.ok) throw new NetworkError(`Failed`, res.status);
} catch (err) {
  if (err instanceof NetworkError && err.status === 401) {
    redirectToLogin();
  } else {
    throw err;
  }
}

finally в асинхронных функциях и ожидании

Блок finally выполняется независимо от того, завершился блок try успешно или с ошибкой, — так же, как завершающая обработка промиса. Используйте его для освобождения ресурсов или скрытия состояния загрузки.

async function loadData() {
  setLoading(true);
  try {
    const data = await fetch('/api/data').then(r => r.json());
    setData(data);
  } catch (err) {
    setError(err.message);
  } finally {
    setLoading(false); // always runs
  }
}

Асинхронная IIFE для точки входа модуля

Оберните точку входа скрипта в асинхронную IIFE, если нельзя использовать ожидание на верхнем уровне.

(async () => {
  const data = await fetchInitialData();
  renderApp(data);
})();

AbortController для отмены

Передайте сигнал AbortController в fetch, чтобы отменить выполняющийся запрос. Отдельная обработка AbortError предотвращает отображение ошибки пользователю.

const controller = new AbortController();

try {
  const data = await fetch(url, { signal: controller.signal }).then(r => r.json());
  setData(data);
} catch (err) {
  if (err.name !== 'AbortError') setError(err.message);
}

// Cancel:
controller.abort();

Быстрая проверка

Какая конструкция правильно обрабатывает ошибки из ожидаемого промиса?

Итоги: асинхронные функции и ожидание

Асинхронные функции всегда возвращают промисы. Ожидание приостанавливает выполнение, пока промис не завершится. Используйте конструкцию обработки ошибок для обработки ошибок. Для параллельных операций применяйте Promise.all(). Не используйте ожидание внутри forEach — применяйте цикл for...of или Promise.all. AbortController отменяет выполняющиеся запросы. Ожидание на верхнем уровне работает в модулях ES.

Часто задаваемые вопросы

Урок «async/await и обработка ошибок» бесплатный?

Да — полный текст урока «async/await и обработка ошибок» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Frontend Academy, подпишись на CoddyKit PRO. Курс Frontend Academy содержит 4 уроков всего.

Чему я научусь в уроке «async/await и обработка ошибок»?

Пишите асинхронные функции с ключевым словом await, оборачивайте ожидаемые вызовы в блоки try/catch и разбирайтесь, почему async/await — это синтаксический сахар над Promise. Ты практикуешь Frontend Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Frontend Academy?

Предыдущий опыт не требуется. Frontend Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «async/await и обработка ошибок»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Frontend Academy?

Да. Каждый урок Frontend Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Цикл событий: стек вызовов, очередь и микрозадачи
  2. Колбэки и ад колбэков
  3. Promise: then, catch, finally и Promise.all
  4. async/await и обработка ошибок
← Назад к Frontend Academy