JavaScript Promise.any: первый успешный результат
Promise.any() ждёт первый успешно выполненный промис и игнорирует отклонения остальных. Если успешных нет, возвращается AggregateError со списком причин. Это удобно для запросов к нескольким зеркалам или CDN: достаточно, чтобы ответил хотя бы один источник.
Получить самый быстрый успешный ответ
const slow = new Promise((resolve) => setTimeout(() => resolve("slow"), 50));
const fast = new Promise((resolve) => setTimeout(() => resolve("fast"), 10));
const failed = Promise.reject(new Error("fail"));
console.log(await Promise.any([slow, failed, fast])); // fastОтклонённый промис не завершает Promise.any, пока есть шанс на успех. В отличие от Promise.race, который завершается первым же результатом, включая ошибку, any ждёт именно успеха. Порядок элементов в массиве не влияет на выбор: решает время выполнения.
Обработать AggregateError
try {
await Promise.any([
Promise.reject(new Error("a")),
Promise.reject(new Error("b")),
]);
} catch (error) {
console.log(error.name); // AggregateError
console.log(error.errors.length); // 2
}AggregateError.errors содержит причины в порядке входного массива, а не в порядке завершения. Проверяйте наличие поля перед обращением, если код может выполняться в старом окружении. Пустой iterable сразу даёт AggregateError с пустым списком ошибок.
Promise.any() поддерживается в Chrome 85+, Firefox 79+, Safari 14+ и Node.js 15+. Он всегда добавляет обработчики ко всем промисам, поэтому отклонения не становятся необработанными. Если нужны все результаты, берите Promise.allSettled; если нужен первый любой — Promise.race.
Не используйте any для операций с побочными эффектами: успешный ответ одного зеркала не отменяет остальные запросы. Для отмены передайте общий AbortController и вызывайте abort() после первого успеха, иначе лишние запросы продолжат работать.
Документация: Promise.any, AggregateError.