PurpleSchool — курсы программирования онлайн
  • Пути
    • Frontend React разработчик
    • Frontend Vue разработчик
    • Backend разработчик Node.js
    • Fullstack разработчик React / Node.js
    • Mobile разработчик React Native
    • Backend разработчик Golang
    • Devops инженер
    • Backend разработчик Python
  • Подписка
  • AI для кодаНовое
  • О нас
    • Отзывы
    • Реферальная программа
    • О компании
    • Контакты
  • Иконка открытия меню
    • PurpleFlow
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
PurpleSchool — платформа бесплатных roadmap и курсов для разработчиков
ютуб иконка
Telegram иконка
VK иконка
VK иконка
Курсы
ГлавнаяКаталог курсовFrontendBackendFullstack
Практика
КарьераПроектыPurpleПлюсPurpleMax
Материалы
БлогБаза знаний
Документы
Договор офертаПолитика конфиденциальностиПроверка сертификатаМиграция курсовРеферальная программа
Реквизиты
ИП Ларичев Антон АндреевичИНН 773373765379contact@purpleschool.ru

PurpleSchool © 2020 -2026 Все права защищены

  • Курсы
    • FrontendИконка стрелки
    • AI разработкаИконка стрелки
    • BackendИконка стрелки
    • DevOpsИконка стрелки
    • MobileИконка стрелки
    • ТестированиеИконка стрелки
    • Soft-skillsИконка стрелки
    • ДизайнИконка стрелки
    Иконка слояПерейти в каталог курсов
  • Бесплатно
    • Курсы
    • JavaScript Основы разработкиPython Основы PythonCSS CSS FlexboxКарта развитияВопросы для собеседований
    • База знанийИконка стрелки
    • Новостные рассылкиИконка стрелки
  • PurpleSchool — курсы программирования онлайн
    • Подписка
    • AI для кодаНовое
    • Сообщество
    Главная
    Сообщество
    Async/await в JavaScript: полное руководство 2024

    Async/await в JavaScript: полное руководство 2024

    Аватар автора Async/await в JavaScript: полное руководство 2024

    Антон Ларичев

    Иконка календаря28 июня 2026
    javascriptasyncawaitpromisesасинхронностьmiddleИконка уровня middle
    Картинка поста Async/await в JavaScript: полное руководство 2024

    Введение

    Асинхронное программирование — один из ключевых навыков JavaScript-разработчика. Долгое время для работы с асинхронным кодом использовались колбэки и промисы, но с появлением async/await в ES2017 код стал значительно чище и понятнее. В этом руководстве разберём всё: от внутреннего устройства до типичных ошибок на практике.

    Почему асинхронность важна

    JavaScript — однопоточный язык. Это означает, что все операции выполняются последовательно в одном потоке. Если заблокировать поток долгим запросом к серверу, интерфейс зависнет и пользователь ничего не сможет сделать.

    Асинхронный код позволяет запускать долгие операции (сетевые запросы, чтение файлов, таймеры) без блокировки основного потока. Пока операция выполняется «в фоне», поток свободен для другой работы.

    Event Loop и очередь задач

    Под капотом async/await работает Event Loop. Когда встречается await, выполнение функции приостанавливается, а управление возвращается вызывающему коду. Когда промис завершается, функция возобновляется с того места, где была остановлена.

    Промисы как основа async/await

    Async/await — это синтаксический сахар над промисами. Чтобы понять async/await, нужно разобраться с промисами.

    Промис — объект, представляющий результат асинхронной операции. Он может находиться в трёх состояниях: pending (ожидание), fulfilled (выполнен успешно), rejected (отклонён с ошибкой).

    // Создание промиса вручную
    const fetchUser = (id) => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          if (id > 0) {
            // Успешно возвращаем пользователя
            resolve({ id, name: 'Иван Петров' });
          } else {
            // Отклоняем с ошибкой при некорректном id
            reject(new Error('Некорректный ID пользователя'));
          }
        }, 1000);
      });
    };

    Синтаксис async/await

    Объявление async-функции

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

    // Обычная async-функция
    async function getUser(id) {
      return { id, name: 'Иван' };
    }
    
    // Стрелочная async-функция
    const getProduct = async (id) => {
      return { id, price: 1500 };
    };
    
    // Оба варианта возвращают промис
    getUser(1).then(user => console.log(user)); // { id: 1, name: 'Иван' }

    Оператор await

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

    async function loadUserProfile(userId) {
      // Ожидаем получения пользователя
      const user = await fetchUser(userId);
      
      // Ожидаем получения постов пользователя
      const posts = await fetchPosts(user.id);
      
      // Ожидаем получения комментариев к постам
      const comments = await fetchComments(posts[0].id);
      
      return { user, posts, comments };
    }

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

    try/catch с async/await

    Ошибки в async/await обрабатываются через стандартный try/catch, что делает код более читаемым по сравнению с цепочками .catch().

    async function loadData(userId) {
      try {
        const user = await fetchUser(userId);
        const posts = await fetchPosts(user.id);
        return { user, posts };
      } catch (error) {
        // Обрабатываем любую ошибку из цепочки await
        console.error('Ошибка загрузки данных:', error.message);
        throw error; // Пробрасываем ошибку выше при необходимости
      } finally {
        // Выполняется всегда — удобно для очистки ресурсов
        console.log('Загрузка завершена');
      }
    }

    Обработка ошибок для каждого await

    Иногда нужно обрабатывать ошибки для каждой операции отдельно:

    async function robustLoad(userId) {
      // Используем .catch() прямо на промисе для локальной обработки
      const user = await fetchUser(userId).catch(() => null);
      
      if (!user) {
        return { error: 'Пользователь не найден' };
      }
      
      const posts = await fetchPosts(user.id).catch(() => []);
      
      return { user, posts };
    }

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

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

    Promise.all

    Promise.all запускает все промисы одновременно и ждёт, пока все завершатся. Если хотя бы один отклоняется — отклоняется весь результат.

    async function loadDashboard(userId) {
      // Неэффективно: запросы выполняются последовательно (3 секунды)
      // const user = await fetchUser(userId);
      // const stats = await fetchStats(userId);
      // const notifications = await fetchNotifications(userId);
    
      // Эффективно: запросы выполняются параллельно (1 секунда)
      const [user, stats, notifications] = await Promise.all([
        fetchUser(userId),
        fetchStats(userId),
        fetchNotifications(userId),
      ]);
    
      return { user, stats, notifications };
    }

    Promise.allSettled

    Promise.allSettled ждёт завершения всех промисов, независимо от того, выполнены они или отклонены. Полезен когда нужны все результаты, даже при частичных ошибках.

    async function loadOptionalData(userId) {
      const results = await Promise.allSettled([
        fetchUser(userId),
        fetchRecommendations(userId), // Необязательные данные
        fetchBadges(userId),          // Необязательные данные
      ]);
    
      // Проверяем статус каждого результата
      const [userResult, recsResult, badgesResult] = results;
    
      return {
        user: userResult.status === 'fulfilled' ? userResult.value : null,
        recommendations: recsResult.status === 'fulfilled' ? recsResult.value : [],
        badges: badgesResult.status === 'fulfilled' ? badgesResult.value : [],
      };
    }

    Promise.race и Promise.any

    async function fetchWithTimeout(url, timeoutMs) {
      // Возвращает результат того промиса, который завершится первым
      const result = await Promise.race([
        fetch(url),
        new Promise((_, reject) =>
          // Отклоняем через заданное время
          setTimeout(() => reject(new Error('Таймаут запроса')), timeoutMs)
        ),
      ]);
      return result;
    }

    Частые ошибки

    Забытый await

    Отсутствие await — одна из самых распространённых ошибок. Без него функция вернёт промис, а не значение.

    async function wrongExample() {
      // Ошибка: переменная содержит промис, а не пользователя
      const user = fetchUser(1);
      console.log(user.name); // undefined
    }
    
    async function correctExample() {
      // Правильно: ожидаем выполнения промиса
      const user = await fetchUser(1);
      console.log(user.name); // 'Иван Петров'
    }

    await в цикле вместо параллелизма

    // Медленно: каждый запрос ждёт предыдущий
    async function slowLoad(ids) {
      const results = [];
      for (const id of ids) {
        const user = await fetchUser(id); // Блокирует следующую итерацию
        results.push(user);
      }
      return results;
    }
    
    // Быстро: все запросы выполняются параллельно
    async function fastLoad(ids) {
      const promises = ids.map(id => fetchUser(id));
      return await Promise.all(promises);
    }

    Потеря контекста ошибки

    async function badErrorHandling() {
      try {
        await riskyOperation();
      } catch (error) {
        // Плохо: теряем оригинальный стек ошибки
        throw new Error('Что-то пошло не так');
      }
    }
    
    async function goodErrorHandling() {
      try {
        await riskyOperation();
      } catch (error) {
        // Хорошо: сохраняем оригинальную ошибку через cause
        throw new Error('Ошибка в riskyOperation', { cause: error });
      }
    }

    Заключение

    Async/await значительно упрощает работу с асинхронным кодом в JavaScript. Ключевые моменты для запоминания: async-функция всегда возвращает промис, await работает только внутри async-функции, независимые операции стоит запускать параллельно через Promise.all, а ошибки обрабатывать через try/catch.

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

    Иконка глаза502

    Комментарии

    0
    Бесплатный курс

    Учитесь программировать с AI-агентом — бесплатно

    Курс «AI в обучении: OpenCode и skills»: поставите агента и разберёте с ним любую тему — как эту статью.

    opencode

    >объясни этот код и дай задачу

    ◆Читаю src/server.ts…

    ✓Разбор готов: 4 шага

    ✓Задача → practice/01.md

    • Установка и настройка OpenCode
    • Агент и skills на практике
    • 13 уроков, 3 модуля
    Начать бесплатно

    0 ₽ · доступ сразу после регистрации

    Бесплатные лекции

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

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

    React и Redux Toolkit

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

    Zustand

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

    Neovim

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

    Похожие статьи

    Картинка поста Claude Code по API-ключу вместо подписки: настройка
    Иконка аватараАнтон
    Иконка календаря10 ноября 2026
    Claude CodeAnthropicAI-инструментыjuniorИконка уровня junior

    Claude Code по API-ключу вместо подписки: настройка

    Как подключить Claude Code по API-ключу вместо подписки: переменные, проверка через /status, приоритет ключа и частые ошибки.

    Иконка чипа0
    Иконка глаза23
    Иконка комментариев0
    Картинка поста Обучение Claude Code: с чего начать, курсы и материалы
    Иконка аватараАнтон
    Иконка календаря09 ноября 2026
    AI-инструментыClaude CodeразработкаjuniorИконка уровня junior

    Обучение Claude Code: с чего начать, курсы и материалы

    С чего начать обучение Claude Code: план на первую неделю, порядок тем, бесплатные материалы, курсы и как получить доступ для практики из России.

    Иконка чипа0
    Иконка глаза109
    Иконка комментариев0
    Картинка поста Qwen Code Desktop: установка и подключение из России
    Иконка аватараАнтон
    Иконка календаря08 ноября 2026
    Qwen CodeAI-инструментыразработкаjuniorИконка уровня junior

    Qwen Code Desktop: установка и подключение из России

    Как скачать и установить Qwen Code Desktop на Windows, macOS и Linux и подключить модели Claude и Qwen из России без VPN: готовый settings.json и частые ошибки.

    Иконка чипа0
    Иконка глаза218
    Иконка комментариев0
    Иконка чипа0