На JavaScript/Node.js есть пример с промисами: Promise.all([p1,p2]).then(results=>{/*...*/}).catch(e=>{/*...*/}) — объясните поведение при частичном провале промисов, как обрабатывать частичные ошибки и какие абстракции (allSettled, race) полезны

3 Мар в 09:13
44 +1
0
Ответы
1
Коротко — что происходит и что использовать.
1) Поведение `Promise.all`
- `Promise.all([p1, p2, ...])` возвращает промис, который:
- разрешится в массив значений, если все входные промисы выполнены (fulfilled) — `then(results => ...)`.
- отклонится (reject) немедленно при первом отклонённом (rejected) промисе, с тем же `reason` — `catch(e => ...)`.
- Важно: «немедленно» значит, что результат общего промиса — reject как только один промис отклонится; остальные промисы при этом продолжают выполняться в фоне. Их возможные последующие rejections будут считаться необработанными, если вы их явно не поймали.
2) Как обрабатывать частичные ошибки
- Если нужна информация по каждому промису (успех/ошибка), используйте `Promise.allSettled`:
```js
const results = await Promise.allSettled([p1, p2, p3]);
// results = [{status: 'fulfilled', value: ...}, {status: 'rejected', reason: ...}, ...]
const successes = results.filter(r => r.status === 'fulfilled').map(r => r.value);
const errors = results.filter(r => r.status === 'rejected').map(r => r.reason);
```
- Альтернативный шаблон — обернуть каждый промис так, чтобы он никогда не отклонялся, а возвращал tagged-объект:
```js
function reflect(p) {
return p.then(v => ({ ok: true, value: v }))
.catch(e => ({ ok: false, error: e }));
}
const results = await Promise.all([p1, p2, p3].map(reflect));
// затем фильтруете по .ok
```
Этот подход полезен, если хотите продолжать работу со всеми результатами и избежать `Promise.all`-reject.
- Если нужно выполнить операции по очереди и при ошибке обрабатывать отдельно, можно `try/catch` вокруг каждого `await` или внутри цикла `for ... of`.
3) Полезные абстракции и паттерны
- `Promise.allSettled(promises)` — получает статусы всех промисов (полезно для частичных успехов).
- `Promise.race(promises)` — возвращает первый settled (fulfill или reject). Полезно для таймаутов:
```js
const timeout = ms => new Promise((_, rej) => setTimeout(() => rej(new Error('timeout')), ms));
const result = await Promise.race([longRunningOp(), timeout(5000)]);
```
- `Promise.any(promises)` — разрешится при первом выполненном промисе; отклонится (с `AggregateError`), если все промисы отклонятся.
- `Promise.all` — быстрый fail-fast; подходит, когда вам нужны все результаты или нет смысла продолжать при любой ошибке.
4) Практические рекомендации
- Если ошибка одного запроса не должна ломать остальные — используйте `allSettled` или `reflect` и обрабатывайте per-item.
- Чтобы избежать unhandled rejections, всегда поймайте возможные ошибки каждого промиса либо явно обработайте результат `allSettled` / обёртку.
- Для таймаутов и «первого ответа» используйте `race`; для «первого успешного» — `any`.
- Для сбора всех ошибок (например, логирования) используйте `allSettled` и собирайте `reason`.
Если нужно — могу показать конкретный пример для вашей задачи (фоновая загрузка множества URLов, групповой rollback и т. п.).
3 Мар в 09:22
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир