Как обрабатывать массив результатов промисов в JavaScript и выводить success или fail в консоль
Что проверяют
Знаете ли вы разницу между комбинаторами промисов и понимаете ли, что происходит с остальными промисами, когда один из них падает. Следом обычно просят переписать решение на async/await или выводить результат по мере завершения каждого промиса, а не в конце.
Как отвечать
Базовое решение через Promise.allSettled (ES2020). Он дожидается всех промисов, из-за упавших не отклоняется и возвращает массив объектов { status: 'fulfilled', value } или { status: 'rejected', reason } в порядке входного массива. Остальные комбинаторы:
- allSettled:
const results = await Promise.allSettled(promises), дальшеresults.forEach(r => console.log(r.status === 'fulfilled' ? 'success' : 'fail')); - all: отклоняется на первой же ошибке. Остальные промисы продолжают выполняться, просто их результаты теряются. Годится, когда без любого из результатов дальше идти бессмысленно;
- any: берёт первый успешный, а если упали все, отклоняется с
AggregateError; - race: первый завершившийся, неважно, успехом или ошибкой. Классический пример: запрос против таймаута.
Если статус нужно печатать сразу, повесьте обработчик на каждый промис: promises.forEach(p => p.then(() => console.log('success'), () => console.log('fail'))). Порядок вывода тогда совпадёт с порядком завершения, а не с порядком в массиве.
Скажите и про параллельность: операция стартует в момент создания промиса, а не когда его передали в allSettled. Если задач тысячи, их запускают порциями или через ограничитель параллельности.
Где спотыкаются
Пишут .catch сразу после Promise.allSettled и считают, что так обработали ошибки. Упавшие промисы туда не попадут, они видны только в status и reason.
Используют forEach с async-колбэком и await внутри. forEach колбэки не ждёт, и код после цикла выполнится раньше, чем что-то выведется.
Ставят await на каждый промис в цикле for...of, думая, что так они выполняются по очереди. Если в массиве уже запущенные промисы, они и так идут параллельно. Для последовательного выполнения в массиве должны лежать функции, которые возвращают промис.