Как обрабатывать ошибки в сетевых запросах
Что проверяют
Разделяете ли вы ошибки по природе (транспорт, HTTP-статус, разбор ответа, отмена) и строите ли для них единую модель в сетевом слое, а не print в колбэке. Следом спрашивают про повторы с задержкой и про поведение приложения без сети.
Как отвечать
Начните с неочевидного факта: URLSession не считает ответы 4xx и 5xx ошибкой. try await URLSession.shared.data(for:) вернёт данные и HTTPURLResponse, статус проверяет ваш код.
- транспорт:
URLErrorс кодами.notConnectedToInternet,.timedOut,.networkConnectionLost,.cannotFindHost. Обычно временные, повтор уместен; - отмена:
URLError.cancelledилиCancellationErrorпри отменеTask. Для пользователя это не ошибка, показывать её не нужно; - HTTP-статусы: на 401 обновить токен и повторить запрос один раз, остальные 4xx не повторять, 5xx и 429 повторять с учётом заголовка
Retry-After; - разбор ответа:
DecodingErrorозначает расхождение контракта. Его логируют с путём до поля и не ретраят; - единый тип: свой
enum NetworkError: Error, в который сетевой слой переводит всё перечисленное. Экран получает понятный случай и сам решает, что показать, текст удобно отдавать черезLocalizedError; - повторы: экспоненциальная задержка с джиттером, лимит попыток и только для идемпотентных запросов;
- без сети:
NWPathMonitorдля состояния подключения,waitsForConnectivityвURLSessionConfiguration, закешированные данные вместо пустого экрана.
Логи пишите через Logger из фреймворка os, а нефатальные ошибки отправляйте в систему сбора сбоев, чтобы видеть их не только на своём устройстве.
Где спотыкаются
Ждут 404 или 500 в параметре error колбэка или в catch. Туда они не попадут: на транспортном уровне запрос прошёл успешно.
Повторяют всё подряд: 400, неидемпотентный POST, без задержки. Сервер, который и так лёг, получает ещё больше нагрузки, а пользователь дважды оформляет заказ.
Показывают пользователю error.localizedDescription или алерт на отмену запроса при уходе с экрана. Сюда же относится обновление интерфейса прямо из колбэка dataTask: он вызывается не на главном потоке.