使用URLSession和Combine处理HTTP状态代码

时间:2019-12-23 21:34:29

标签: swift urlsession combine

我正在尝试处理从DataTaskPublisher读取其响应状态代码而来的响应。

当状态码大于299时,我想返回ServiceError类型作为Failure。在我看到的每个示例中,我都使用过.mapError的{​​{1}}和.catch ...在这种特定情况下,我真的不知道如何处理发布者响应以返回错误而不是.flatMap ...

TResponse

2 个答案:

答案 0 :(得分:2)

enum ServiceErrors { 
    case internalError(_ statusCode: Int)
    case severError(_ statusCode: Int)
}

return URLSession.shared.dataTaskPublisher(for: urlRequest)
            .tryMap { data, response in
                guard let httpResponse = response as? HTTPURLResponse,
                    200..<300 ~= httpResponse.statusCode else {
                        switch (response as! HTTPURLResponse).statusCode {
                        case (400...499):
                            throw ServiceErrors.internalError((response as! HTTPURLResponse).statusCode)
                        default:
                            throw ServiceErrors.serverError((response as! HTTPURLResponse).statusCode)
                        }
                }
                return data
            }
            .mapError { $0 as! ServiceErrors }
            .decode(type: T.self, decoder: JSONDecoder())
            .receive(on: RunLoop.main)
            .eraseToAnyPublisher()

我依靠此链接来创建我的错误处理程序https://gist.github.com/stinger/7cb1a81facf7f846e3d53f60be34dd1e

答案 1 :(得分:1)

如果我正确理解了您的目标,则需要类似

}else{
    return Fail(error: ServiceError.badServiceReply)
              .eraseToAnyPublisher()
}

简单的例子:

URLSession.shared
    .dataTaskPublisher(for: URL(string: "https://www.google.com")!)
    .receive(on: DispatchQueue.main)
    .flatMap { _ in
        Fail(error: URLError(URLError.unsupportedURL)).eraseToAnyPublisher()
    } //for the sake of the demo
    .replaceError(with: "An error occurred") //this sets Failure to Never
    .assign(to: \.stringValue, on: self)
    .store(in: &cancellableBag)

由于重新映射到Fail发布者,总是会分配字符串“发生错误”