> Как записывать ошибки в массив по индексу, соответствующему индексу промиса в JavaScript? (JavaScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: Яндекс
Стек: JavaScript
> Пример ответа
Короткий ответ
Для записи ошибок в массив по индексу, соответствующему индексу промиса, используйте Promise.allSettled или Promise.all с обработкой каждого промиса через .catch. В Promise.allSettled каждый результат содержит status и value или reason, что позволяет сопоставить ошибку с исходным индексом. Альтернативно - маппинг промисов с сохранением индекса через Promise.all и массив ошибок фиксированной длины.
Подробное объяснение
Основная задача - сохранить соответствие между порядком промисов в исходном массиве и ошибками, которые могут возникнуть при их выполнении. Это важно для асинхронных операций, где нужно точно знать, какой именно промис упал.
Promise.allSettled - наиболее прямой путь: он возвращает массив объектов с полями status ("fulfilled" или "rejected"), value и reason. Индекс объекта в результирующем массиве совпадает с индексом исходного промиса. Затем можно пройтись по результатам и собрать ошибки в массив по тем же индексам.
Promise.all не подходит напрямую, так как при первом rejection он сразу переходит в catch, теряя информацию об остальных промисах. Однако можно обернуть каждый промис в .catch, который возвращает объект ошибки, и тогда Promise.all дождётся всех. При этом нужно сохранить индекс - например, через Promise.all(promises.map((p, i) => p.catch(err => ({ index: i, error: err })))).
Для точного соответствия индексов удобно заранее создать массив ошибок фиксированной длины, заполненный null, и заполнять его по индексу при обработке каждого промиса.
На практике
В реальных проектах часто нужно загрузить несколько ресурсов параллельно и понять, какой именно не загрузился. Например, при загрузке изображений или данных для разных виджетов на странице. Использование Promise.allSettled даёт полную картину без потери информации.
Если требуется только массив ошибок, а успешные результаты не нужны, можно комбинировать Promise.allSettled с фильтрацией. Для критичных операций, где важен порядок, лучше явно сохранять индекс при обработке.
Пример кода
JAVASCRIPT// Исходный массив промисовconst promises = [fetch('/api/data1'),fetch('/api/data2'),fetch('/api/data3')];// Вариант 1: Promise.allSettledasync function collectErrorsWithAllSettled(promises) {const results = await Promise.allSettled(promises);const errors = new Array(promises.length).fill(null);results.forEach((result, index) => {if (result.status === 'rejected') {errors[index] = result.reason;}});return errors; // [null, Error, null] - ошибка только у второго промиса}// Вариант 2: Promise.all с сохранением индексаasync function collectErrorsWithAll(promises) {const errors = new Array(promises.length).fill(null);const wrapped = promises.map((p, i) =>p.catch(err => {errors[i] = err;return undefined; // возвращаем что-то, чтобы Promise.all не упал}));await Promise.all(wrapped);return errors;}
Как отвечать на собеседовании
Начните с прямого ответа: используйте Promise.allSettled. Затем объясните, почему это предпочтительнее Promise.all - из-за обработки всех результатов, а не только первого rejection. Упомяните, что для точного соответствия индексов можно заранее создать массив ошибок. Если спросят про производительность, отметьте, что Promise.allSettled незначительно медленнее из-за дополнительной обёртки, но это оправдано надёжностью. Приведите пример из реальной практики, например, параллельная загрузка данных для дашборда.
Что проверяет интервьюер
Интервьюер оценивает понимание асинхронности в JavaScript, знание методов работы с промисами (Promise.all, Promise.allSettled, Promise.race), умение обрабатывать ошибки без потери контекста. Также проверяется способность проектировать надёжные асинхронные операции, где важна целостность данных. Senior-уровень подразумевает не только знание API, но и понимание trade-off между разными подходами.
Типичные ошибки
- Использование
Promise.allбез обёртки.catch- теряются все ошибки кроме первой. - Путаница между
Promise.allSettledиPromise.all- первый ждёт все промисы, второй падает при первом rejection. - Игнорирование необходимости сохранять индекс - например, просто пуш в массив ошибок без привязки к порядку.
- Забывание про
nullв массиве для успешных промисов - массив ошибок должен иметь ту же длину, что и исходный массив промисов. - Неправильная обработка вложенных асинхронных операций - если внутри промиса есть ещё асинхронность, нужно убедиться, что ошибка пробрасывается корректно.
> Похожие задачи по frontend
Как реализовать полифилл для Array.prototype.some с учетом callback и thisArg?
Как использовать несколько потоков в JavaScript
Что такое замыкания в JavaScript и для чего они нужны
Как реализовать рекурсивную чистую функцию для инверсии значений в объекте в JavaScript
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью