Що робить Promise.race()?
Що робить Promise.race()
Promise.race(iterable) приймає масив (або будь-який ітерований об'єкт) промісів
і повертає новий проміс, який:
- виконується (
fulfilled) або відхиляється (rejected), щойно перший із переданих промісів завершиться - незалежно від того, успішно чи з помилкою.
Тобто "перегони" промісів: хто перший завершиться - той і визначить результат.
Синтаксис
Promise.race(iterable)Повертає:
новий Promise, який:
- завершиться зі значенням першого успішно виконаного промісу (
resolve), - або впаде з помилкою, якщо першим завершиться той, що зробив
reject.
Приклад 1 - хто швидший, той і переміг
const fast = new Promise(resolve => setTimeout(() => resolve('Швидкий'), 1000));
const slow = new Promise(resolve => setTimeout(() => resolve('Повільний'), 3000));
Promise.race([fast, slow]).then(console.log);Результат через 1 секунду:
ШвидкийДругий проміс (slow) продовжить виконуватися у фоні,
але результат уже визначено - "перегони" виграв fast.
Приклад 2 - якщо перший проміс завершився з помилкою
const ok = new Promise(resolve => setTimeout(() => resolve('Все гаразд'), 2000));
const fail = new Promise((_, reject) => setTimeout(() => reject('Помилка!'), 1000));
Promise.race([ok, fail])
.then(console.log)
.catch(console.error);Результат через 1 секунду:
Помилка!Навіть попри те, що ok потім успішно виконається,
результат усіх перегонів уже вирішено помилкою.
Як це працює під капотом
- Усі проміси починають виконуватися одночасно (практично).
- Щойно один з них завершився (
resolveабоreject):
- результат цього промісу стає результатом усіх перегонів;
Promise.race()переходить у станfulfilledабоrejected;- інші проміси ігноруються (але не скасовуються).
- Решта промісів продовжують виконуватися у фоні, але їхній результат ні на що не впливає.
Приклад 3 - з "таймаутом"
Часта практика: використовувати Promise.race() для встановлення обмеження за часом
function timeout(ms) {
return new Promise((_, reject) =>
setTimeout(() => reject(`Перевищено час очікування (${ms}мс)`), ms)
);
}
const fetchData = new Promise(resolve =>
setTimeout(() => resolve('Відповідь отримано'), 3000)
);
Promise.race([fetchData, timeout(2000)])
.then(console.log)
.catch(console.error);Вивід через 2 секунди:
Перевищено час очікування (2000мс)Це один з найчастіших сценаріїв застосування Promise.race() -
обмеження "зависаючих" операцій (наприклад, запитів).
Приклад 4 - усі проміси миттєві
Promise.race([
Promise.resolve('Перший'),
Promise.resolve('Другий'),
Promise.resolve('Третій')
]).then(console.log);Вивід:
ПершийНавіть якщо всі виконаються миттєво - перемагає перший за порядком ітерації.
Якщо передати не-проміси
Promise.race() автоматично "обгортає" звичайні значення в Promise.resolve():
Promise.race([42, Promise.resolve('OK')]).then(console.log); // 42Відмінність від інших методів
| Метод | Що робить | Завершується коли | При помилці |
|---|---|---|---|
Promise.all() | Чекає всі проміси | Усі завершено успішно | Падає при першому reject |
Promise.allSettled() | Чекає всіх, незалежно від результату | Усі завершено | Ніколи не падає |
Promise.race() | Бере перший завершений | Перший resolve або reject | Залежить від першого промісу |
Promise.any() | Бере перший успішний (resolve) | Перший fulfilled | Падає, якщо всі rejected |
Проста аналогія
Уяви перегони.
У тебе кілька кур'єрів - хто перший доставить посилку, того результат ти й приймаєш. Решта все ще в дорозі, але тобі вже байдуже, ти отримав потрібне.
ПІДСУМОК
| Особливість | Promise.race() |
|---|---|
| Приймає | Масив (або інший ітерований об'єкт) промісів |
| Завершується коли | Перший проміс виконається або відхилиться |
| Повертає | Результат (або помилку) першого завершеного промісу |
| Решта промісів | Ігноруються (але не скасовуються) |
| Часте застосування | Обмеження за часом (timeout), конкуренція запитів |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.