Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос нашим менторам. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.
Об обучении на Хекслете
JS: Асинхронное программирование

Promise.all

Промисы, как и колбеки, позволяют выполнять асинхронные операции параллельно. Причём умеют делать это в автоматическом режиме, без ручного отслеживания окончания одной из операций. Для этого достаточно собрать массив из промисов и передать их в функцию Promise.all. В результате вернётся обычный промис, на основе которого можно строить дальнейшую цепочку. Данными в первом then будет массив с данными всех выполненных операций.

import { promises as fsp } from 'fs';

const unionFiles = (inputPath1, inputPath2, outputPath) => {
  const promise1 = fsp.readFile(inputPath1, 'utf-8');
  const promise2 = fsp.readFile(inputPath2, 'utf-8');
  // На вход идет МАССИВ из промисов
  const promise = Promise.all([promise1, promise2]);
  // Обязательно делать возврат!
  return promise.then(([data1, data2]) => fsp.writeFile(outputPath, `${data1}${data2}`));
};

Получился эффективный код, который ещё и легко понять. К тому же здесь нет дополнительных переменных. Promise.all хоть и возвращает данные в том же порядке, в котором в него были переданы промисы, но не гарантирует последовательность выполнения операций. Не рассчитывайте на это никогда, все операции запускаются одновременно, и какая из них выполнится раньше или позже — неизвестно.

Функции Promise.all не важно, каким образом была получена коллекция промисов. Единственное, что ей нужно – получить на вход массив этих промисов. Поэтому Promise.all легко комбинируется с любыми функциями, возвращающими коллекции. В примере ниже дается массив путей до файлов, которые нужно прочитать и вывести на экран их содержимое. Первым делом в коде формируется массив из промисов, затем он передается в Promise.all и, наконец, содержимое файлов выводится на экран:

// promises – массив промисов
const promises = filepaths.map((filepath) => fsp.readFile(filepath, 'utf-8'));
const promise = Promise.all(promises);
// Выводим на экран содержимое каждого файла
promise.then((contents) => contents.map(console.log));

map проходится по каждому файлу, и отдает его в нашу функцию, которая выполняет вызов fsp.readFile(). Каждый такой вызов возвращает промис. Если попробовать распечатать этот массив, то он будет выглядеть так:

const promises = filepaths.map((filepath) => fsp.readFile(filepath, 'utf-8'));
console.log(promises);
[
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> },
  ...
]

Promise.all всегда запускает операции одновременно, и эти операции друг от друга никак не зависят. Это значит, что никакая ошибка (кроме остановки программы) не остановит запросы. Ошибка хотя бы в одном из промисов не помешает выполниться всем остальным запросам. Однако, если хотя бы один промис завершился с ошибкой, весь результат Promise.all будет помечен как ошибочный, а значит управление попадёт в ближайший catch. Чтобы этого избежать, можно передавать в Promise.all не просто промисы, а промисы с повешенными на них обработчиками ошибок catch, из которых уже возвращаются данные с пометкой об успешности.

const promises = filepaths.map((filepath) => fsp.readFile(filepath, 'utf-8')
  .then((v) => ({ result: 'success', value: v }))
  .catch((e) => ({ result: 'error', error: e })));
const promise = Promise.all(promises);

Дополнительные материалы

  1. Promise.all

<span class="translation_missing" title="translation missing: ru.web.courses.lessons.mentors.mentor_avatars">Mentor Avatars</span>

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят менторы из команды Хекслета или другие студенты.

Для полного доступа к курсу нужна профессиональная подписка

Профессиональная подписка откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, даст возможность обращаться за помощью к менторам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
115
курсов
892
упражнения
2241
час теории
3196
тестов

Зарегистрироваться

или войти в аккаунт

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 115 курсов, 2000+ часов теории
  • 800 практических заданий в браузере
  • 250 000 студентов

Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг».

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Rambler
Логотип компании Bookmate
Логотип компании Botmother

Есть вопрос или хотите участвовать в обсуждении?

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг».