<MyRusakov.ru />

Профессия Web-разработчик

Профессия Web-разработчик

Этот комплект за 8 месяцев превратит Вас в Web-разработчика с нуля. Учиться достаточно 1 час в день.

Начнёте Вы с HTML, CSS и вёрстки сайтов. Потом перейдёте к программированию и JavaScript. Затем изучите PHP, MySQL, SQL, Python. Изучите Web-фреймворки Laravel и Django. Создадите 5 своих сайтов для портфолио.

Комплект содержит:

- 540 видеоуроков

- 110 часов видео

- 1205 заданий для закрепления материала из уроков

- 5 финальных тестов

- 7 сертификатов

- 12 Бонусных курсов

Подробнее
Подписка

Подпишитесь на мой канал на YouTube, где я регулярно публикую новые видео.

YouTube Подписаться

Подписавшись по E-mail, Вы будете получать уведомления о новых статьях.

Подписка Подписаться

Добавляйтесь ко мне в друзья ВКонтакте! Отзывы о сайте и обо мне оставляйте в моей группе.

Мой аккаунт Мой аккаунт Моя группа
Опрос

Какая тема Вас интересует больше?

Промисы и async/await в JavaScript: понятное руководство с примерами и лучшими практиками

Промисы и async/await в JavaScript: понятное руководство с примерами и лучшими практиками

Промисы и async/await в JavaScript: понятное руководство с примерами и лучшими практиками

Запрос: «промисы в JavaScript для начинающих», «async await примеры». Это руководство поможет быстро освоить асинхронный код, избежать частых ошибок и писать надёжно и читаемо.

Что такое промис простыми словами

Promise — это объект, который представляет результат асинхронной операции: «ожидание» (pending), «успех» (fulfilled) или «ошибка» (rejected). Работать с ним можно через then/catch/finally или с помощью синтаксиса async/await.

const p = new Promise((resolve, reject) => {
  setTimeout(() => resolve(42), 500);
});

p
  .then(value => value * 2)
  .then(double => console.log('Результат:', double))
  .catch(err => console.error('Ошибка:', err))
  .finally(() => console.log('Готово'));

async/await: тот же промис, но читабельнее

async-функция возвращает промис. Оператор await «ждёт» промис и возвращает его значение или бросает исключение при отклонении.

async function run() {
  try {
    const value = await p; // 42 через ~500 мс
    console.log('Результат:', value * 2);
  } catch (e) {
    console.error('Ошибка:', e);
  } finally {
    console.log('Готово');
  }
}

run();

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

Частая ошибка — выполнять независимые задачи последовательно вместо параллельного запуска. Сравним:

// Эмулятор загрузки
const load = (id) => new Promise(res => setTimeout(() => res(`item-${id}`), 300));
const ids = [1, 2, 3, 4];

// Плохо: последовательно (дольше)
async function sequential() {
  const out = [];
  for (const id of ids) {
    out.push(await load(id));
  }
  return out;
}

// Хорошо: параллельно
async function parallel() {
  return Promise.all(ids.map(load));
}

sequential().then(r => console.timeEnd('seq'));
console.time('seq');
parallel().then(r => console.timeEnd('par'));
console.time('par');

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

Полезные комбинаторы: all, allSettled, race, any

// 1) Ждём всех, падаем если хоть один упадёт
await Promise.all([taskA(), taskB(), taskC()]);

// 2) Ждём всех, всегда получаем статусы
const results = await Promise.allSettled([taskA(), taskB()]);
// results: [{ status: 'fulfilled', value }, { status: 'rejected', reason }]

// 3) Кто быстрее — тот и результат (включая ошибку)
const first = await Promise.race([slowTask(), fastTask()]);

// 4) Ждём первый успешный, если все упали — AggregateError
try {
  const ok = await Promise.any([mayFail1(), mayFail2()]);
} catch (e) {
  // e instanceof AggregateError
}

Таймауты и отмена: практичные шаблоны

Таймаут через Promise.race:

function withTimeout(promise, ms) {
  const timeout = new Promise((_, reject) =>
    setTimeout(() => reject(new Error(`Timeout ${ms}ms`)), ms)
  );
  return Promise.race([promise, timeout]);
}

// Пример:
await withTimeout(load(1), 500);

Отмена через AbortController (поддерживается fetch и многими API):

const controller = new AbortController();
const { signal } = controller;

setTimeout(() => controller.abort(), 2000); // отменим через 2с

try {
  const res = await fetch('https://example.com/data', { signal });
  const data = await res.json();
  console.log(data);
} catch (e) {
  if (e.name === 'AbortError') {
    console.warn('Запрос отменён');
  } else {
    console.error('Ошибка запроса', e);
  }
}

Типичные ошибки и как их избежать

  • Забыли вернуть промис в .then — цепочка «теряется». Решение: всегда return внутри then, если используете цепочки.
  • Смешивание then и await в одном фрагменте — ухудшает читаемость. Выберите один стиль на участок кода.
  • async в forEach. forEach не ждёт промисы — используйте for...of или map + Promise.all.
  • Нет обработки ошибок — получите unhandledrejection. Всегда ловите ошибки try/catch или .catch.

Пример с forEach: как правильно

// Плохо: не ждёт завершения
ids.forEach(async (id) => {
  await load(id);
});

// Хорошо 1: последовательная обработка
for (const id of ids) {
  await load(id);
}

// Хорошо 2: параллельно и ждём всех
await Promise.all(ids.map(id => load(id)));

Преобразование колбэков в промисы (promisify)

Иногда встречаются функции формата callback(err, result). Их удобно оборачивать в промисы.

function toPromise(fn) {
  return (...args) => new Promise((resolve, reject) => {
    fn(...args, (err, result) => (err ? reject(err) : resolve(result)));
  });
}

// Пример с псевдо-колбэком
function legacyMultiply(x, cb) {
  setTimeout(() => cb(null, x * 2), 200);
}

const multiplyAsync = toPromise(legacyMultiply);
const value = await multiplyAsync(5); // 10

Ограничение конкуренции (concurrency limit)

Не всегда можно запускать сотни запросов параллельно — лимиты и ресурсы не бесконечны. Используйте паттерн mapLimit.

async function mapLimit(items, limit, iteratee) {
  const results = [];
  const executing = new Set();

  for (const item of items) {
    const p = Promise.resolve()
      .then(() => iteratee(item))
      .then((res) => {
        results.push(res);
        executing.delete(p);
      });

    executing.add(p);
    if (executing.size >= limit) {
      await Promise.race(executing);
    }
  }

  await Promise.all(executing);
  return results;
}

// Пример использования
const out = await mapLimit(ids, 2, load); // максимум 2 одновременные задачи

Чеклист лучших практик

  • Независимые задачи запускайте через Promise.all — это быстрее.
  • Добавляйте таймауты к сетевым операциям и умейте отменять (AbortController).
  • Стандартизируйте стиль: либо then-цепочки, либо async/await на участке кода.
  • Ловите ошибки: try/catch и .catch; логируйте и показывайте понятные сообщения.
  • Следите за конкуренцией: используйте лимиты и очереди для тяжёлых задач.
  • Не используйте async в forEach/Map/Filter без понимания поведения — применяйте for...of или Promise.all.

Куда двигаться дальше

Закрепить тему можно на реальных мини-проектах: параллельная загрузка ресурсов с лимитом, отмена долгих запросов, обработка частично успешных результатов через allSettled. Если хотите системно пройти основы и быстро перейти к уверенной практике, загляните сюда: Освоить асинхронность и не только на курсе «JavaScript с Нуля до Гуру 2.0» — стартуйте сегодня.

Промисы и async/await — фундамент современного JavaScript. Освоив их, вы пишете менее «шумный» и более надёжный код, контролируете конкурентность и уверенно обрабатываете ошибки.

Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (https://myrusakov.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: https://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: https://vk.com/rusakovmy.

Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

  1. Кнопка:

    Она выглядит вот так: Как создать свой сайт

  2. Текстовая ссылка:

    Она выглядит вот так: Как создать свой сайт

  3. BB-код ссылки для форумов (например, можете поставить её в подписи):

Комментарии (0):

Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.