В чем разница между Promise.all и Promise.any?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Различие между Promise.all и Promise.any в JavaScript
В современной асинхронной разработке на JavaScript обе функции являются методами класса Promise, но решают принципиально разные задачи и имеют кардинально различающееся поведение.
Promise.all: Ожидание ВСЕХ промисов
Promise.all используется, когда необходимо дождаться выполнения всех переданных промисов. Этот метод принимает итерируемую коллекцию промисов и возвращает новый промис.
Ключевые характеристики Promise.all:
- Возвращает массив результатов в том же порядке, что и исходные промисы
- Если все промисы выполняются успешно, итоговый промис переходит в состояние fulfilled
- Если хотя бы один промис завершается с ошибкой, итоговый промис немедленно переходит в состояние rejected с этой ошибкой
- Гарантирует выполнение всех промисов, но прерывается при первой ошибке
- Полезен для параллельного выполнения независимых операций, где нужны все результаты
// Пример использования Promise.all
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3])
.then((values) => {
console.log(values); // [3, 42, "foo"]
})
.catch((error) => {
console.error('Один из промисов завершился ошибкой:', error);
});
// Пример с ошибкой
const promises = [
Promise.resolve('успех 1'),
Promise.reject(new Error('ошибка!')),
Promise.resolve('успех 3')
];
Promise.all(promises)
.then(results => console.log(results))
.catch(error => console.error(error.message)); // "ошибка!" - выполнение прервано
Promise.any: Ожидание ПЕРВОГО успешного промиса
Promise.any (добавлен в ES2021) используется, когда достаточно получить результат первого успешно выполнившегося промиса. Этот метод принимает итерируемую коллекцию промисов и возвращает новый промис.
Ключевые характеристики Promise.any:
- Возвращает результат первого успешно завершившегося промиса
- Если хотя бы один промис выполняется успешно, итоговый промис переходит в состояние fulfilled с этим результатом
- Если все промисы завершаются с ошибкой, итоговый промис переходит в состояние rejected с агрегированной ошибкой AggregateError
- Полезен для реализации механизмов fallback или выбора самого быстрого источника данных
// Пример использования Promise.any
const promiseFast = new Promise((resolve, reject) => {
setTimeout(reject, 100, 'Быстрый провал');
});
const promiseMedium = new Promise((resolve) => {
setTimeout(resolve, 200, 'Средний успех');
});
const promiseSlow = new Promise((resolve) => {
setTimeout(resolve, 300, 'Медленный успех');
});
Promise.any([promiseFast, promiseMedium, promiseSlow])
.then((value) => {
console.log('Первый успешный результат:', value); // "Средний успех"
})
.catch((error) => {
console.error('Все промисы завершились ошибкой:', error);
});
// Пример, когда все промисы завершаются ошибкой
const rejectedPromises = [
Promise.reject(new Error('Ошибка 1')),
Promise.reject(new Error('Ошибка 2')),
Promise.reject(new Error('Ошибка 3'))
];
Promise.any(rejectedPromises)
.then(result => console.log(result))
.catch(error => {
console.error('Все промисы отклонены');
console.error(error instanceof AggregateError); // true
console.error(error.errors.length); // 3
});
Сравнительная таблица
| Критерий | Promise.all | Promise.any |
|---|---|---|
| Цель | Получить все результаты | Получить первый успешный результат |
| Успех | Когда все промисы успешны | Когда хотя бы один промис успешен |
| Ошибка | Когда хотя бы один промис отклонен | Когда все промисы отклонены |
| Результат при успехе | Массив всех результатов в порядке промисов | Значение первого успешного промиса |
| Результат при ошибке | Первая возникшая ошибка | AggregateError со всеми ошибками |
| Использование | Параллельные независимые операции | Fallback стратегии, быстрый ответ |
Практические сценарии применения
Для Promise.all:
- Загрузка данных из нескольких независимых API
- Параллельное выполнение нескольких запросов к базе данных
- Одновременная загрузка изображений и других ресурсов
- Валидация нескольких условий одновременно
Для Promise.any:
- Запрос к нескольким CDN для получения самого быстрого ответа
- Резервные источники данных (primary, secondary, tertiary)
- Обращение к нескольким сервисам с одинаковой функциональностью
- Реализация timeout с альтернативными вариантами
Особенности поведения
Важно отметить, что Promise.any принципиально отличается от Promise.race, который завершается с результатом первого промиса вне зависимости от того, успешен он или нет. Promise.any же игнорирует отклоненные промисы и ждет именно первого успешного результата.
В контексте тестирования и QA Automation понимание этих различий критически важно для:
- Тестирования асинхронных операций и правильной обработки сценариев
- Написания надежных e2e тестов с использованием асинхронных вызовов
- Моделирования различных сценариев (успех, частичный успех, полный провал)
- Обработки таймаутов и fallback-логики в тестах
Оба метода значительно упрощают работу с асинхронным кодом, но выбор между ними должен основываться на конкретных требованиях бизнес-логики приложения.