You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Combine配合URLSession开发时如何捕获无网络错误并统一封装所有异常

问题原因

URLSession.DataTaskPublisher遇到无网络连接、无法连接服务端、请求超时等系统级错误时,会直接发送Failure类型的错误事件,不会进入tryMap执行逻辑,因此这类错误无法被原有逻辑处理。
你之前使用mapError报错,是因为mapError仅用于转换Publisher的错误类型,无法将错误事件转换为正常的输出值(即你需要的Resource实例)。

解决方案

使用Combine的catch操作符捕获上游所有错误,将错误事件转换为输出Resource.networkError(data: nil)的Publisher即可,修改后的代码如下:

func request<T>(type: T.Type, urlRequest: URLRequest) -> AnyPublisher<Resource<Response<T>>, Never> where T : GenericDecodable {
    return URLSession.shared.dataTaskPublisher(for: urlRequest)
        .tryMap({ try NetworkController.handleURLResponse(output: $0, url: urlRequest) })
        // 捕获所有上游错误,转换为对应的Resource返回值
        .catch { _ in Just(Resource.networkError(data: nil)) }
        .receive(on: DispatchQueue.main)
        .eraseToAnyPublisher()
}

修改后Publisher的错误类型会变为Never,订阅方无需再处理错误事件,所有场景的返回结果都会通过正常的输出通道传递。

如果需要针对不同网络错误做细分处理,可以在catch闭包里做类型判断:

.catch { error in
    if let urlError = error as? URLError {
        switch urlError.code {
        case .notConnectedToInternet:
            // 无网络场景可单独返回对应状态
            return Just(Resource.networkError(data: nil))
        case .cannotConnectToHost, .timedOut:
            return Just(Resource.networkError(data: nil))
        default:
            return Just(Resource.networkError(data: nil))
        }
    }
    // 其他类型错误统一处理
    return Just(Resource.networkError(data: nil))
}

内容的提问来源于stack exchange,提问作者Tolgay Toklar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 19:24:02