gpt4 book ai didi

iOS 组合 : get a strongly typed error from URLSession's dataTaskPublisher

转载 作者:行者123 更新时间:2023-12-01 15:42:45 26 4
gpt4 key购买 nike

我正在努力从 URLSession 的 ApiErrorResponse 形成一个强类型错误对象(我下面示例中的 .dataTaskPublisher(for:) 对象)出版商,但找不到线索。在这里,我创建了一个从远程 API 获取笑话对象的类,然后我按如下方式处理结果和错误(该类可以按 Xcode Playgrounds 中的原样编译):

class DadJokes {

struct Joke: Codable {
let id: String
let joke: String
}

enum Error: Swift.Error {
case network
case parsing(apiResponse: ApiErrorResponse)
case unknown(urlResponse: URLResponse)
}

struct ApiErrorResponse: Codable {
let code: Int
let message: String
}

func getJoke(id: String) -> AnyPublisher<Joke, Error> {
let url = URL(string: "https://myJokes.com/\(id)")!
var request = URLRequest(url: url)
request.allHTTPHeaderFields = ["Accept": "application/json"]
return URLSession.shared
.dataTaskPublisher(for: request)
.map(\.data)
.decode(type: Joke.self, decoder: JSONDecoder())
.mapError { error -> DadJokes.Error in
switch error {
case is DecodingError:
//(1) <--- here I want to get the URLResponse.data from the upstream dataTaskPublisher to decode an object of type ApiErrorResponse (which is returned by the remote API) and pass it to the parsing error case
return .parsing(apiResponse: ApiErrorResponse(code: 1, message: "test"))
case is URLError:
return .network
default:
//(2) <---- here I want to get the URLResponse object that is emitted from the upstream dataTaskPublisher and pass it to the .unknown error case
// I need the URLResponse to read the underlying error info for debugging purposes
return .unknown(urlResponse: URLResponse())
}
}
.eraseToAnyPublisher()
}
}

我有三个问题,其中两个在上面的代码中有注释。第三个是:我应该怎么做才能从 getJoke 返回一个永不失败的发布者?功能 ?即我需要函数的返回类型为 AnyPublisher<Result<Joke, Error>, Never>

最佳答案

首先,我建议稍微修改错误枚举以将 URLError 添加到 .network 案例中。否则,您无法记录有关网络级错误的信息。 (但这并不真正影响答案的其余部分。)

enum Error: Swift.Error {
case network(URLError)
case parsing(apiResponse: ApiErrorResponse)
case unknown(URLResponse)
}

对于核心问题,如果你想要 URLResponse,那么你不能通过调用 .map(\.data) 这么快就把它扔掉。您需要保留它,直到您决定是否需要它。

您还需要考虑来自 API 的数据未解码为 Joke 或 ApiErrorResponse 等情况。这是可能的,您必须处理它。

由于这变得有点复杂,最好留下基本的 .decode 并直接在您自己的 .map 中处理这些情况:

    return URLSession.shared
.dataTaskPublisher(for: request)
.map { (data, response) -> Result<Joke, Error> in
// Either decode a Joke
if let joke = try? JSONDecoder().decode(Joke.self, from: data) {
return .success(joke)
}

// or if that fails, try to decode an error
else if let apiResponse = try? JSONDecoder().decode(ApiErrorResponse.self, from: data) {
return .failure(.parsing(apiResponse: apiResponse))
}

// Wasn't either of those; return the whole response
else {
return .failure(.unknown(response))
}
}
.catch { Just(.failure(.network($0))) } // And also catch errors from dataTaskPublisher
.eraseToAnyPublisher()

关于iOS 组合 : get a strongly typed error from URLSession's dataTaskPublisher,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62986052/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com