Какие тактики обработки ошибок в асинхронных функциях используются?
Что проверяют
Понимаете ли вы, как ошибка проходит через async/await и промисы, и умеете ли ловить её так, чтобы автотест падал честно, а не зеленел по недосмотру. Следом обычно спрашивают, как проверить, что функция действительно отклоняет промис, и что будет с необработанным отказом.
Как отвечать
Начните с механики, потом перейдите к тестам. Для автотестов на JS/TS каркас такой:
try/catchвокругawait: ловит отказ промиса как обычное исключение. Работает, только еслиawaitстоит внутри блока, промис безawaitулетит мимо;.catch()в цепочке: то же для кода наthen. Обработчик в конце цепочки ловит ошибку любого предыдущего шага;Promise.allпротивPromise.allSettled: первый падает на первой же ошибке, второй дожидается всех и отдаёт статус каждого. Для пачки независимых проверок данных нужен второй;- таймауты и отмена:
AbortSignal.timeout(ms)дляfetch, свои таймауты в раннере, чтобы зависший запрос не держал весь прогон; - ретраи: только для заведомо нестабильных внешних вызовов и с ограничением числа попыток, иначе они прячут настоящий баг;
- глобальный уровень: в Node.js необработанный отказ промиса по умолчанию роняет процесс, в браузере его видно через событие
unhandledrejection.
Для тестов назовите конкретику: в Jest и Vitest это await expect(fn()).rejects.toThrow(), в Playwright каждое expect по локатору асинхронное и требует await. Если пишете на Python, аналог это pytest.raises в асинхронном тесте под pytest-asyncio и asyncio.gather(..., return_exceptions=True) для пачки вызовов.
Где спотыкаются
Забывают await перед проверкой. Тест завершается раньше, чем промис отклонится, и проходит зелёным. Ловит это правило линтера @typescript-eslint/no-floating-promises.
Глотают ошибку в catch: пишут console.log и не пробрасывают дальше. Функция возвращает undefined, а упавший шаг выглядит как успешный.
Проверяют только «счастливый путь». Для асинхронного кода надо отдельно гонять отказ сети, ответ 500, таймаут и частичный успех в Promise.allSettled.