合并多个错误处理
Combine multiple errors handling
我决定将标准网络调用迁移到使用 combine 及其运算符的调用。
给定以下代码
enum NetworkServiceError: Error{
case badUrl
case networkFail(String)
}
func getHtml(from url: String, completion: @escaping (Result<String, NetworkServiceError>) -> ()) {
guard let url = URL(string: url) else {
completion(.failure(.badUrl))
return
}
URLSession.shared.dataTask(with: url) { (data, _, error) in
if let err = error{
completion(.failure(.networkFail(err.localizedDescription)))
return
}
guard let rawHtmlData = data else {
completion(.failure(.networkFail("No data")))
return
}
guard let html = String(data: rawHtmlData, encoding: .utf8) else {
completion(.failure(.networkFail("String serialization failed")))
return
}
completion(.success(html))
}
.resume()
}
我希望在 combine 对应物中有同样精确的错误处理。
老实说,尽管我看了很多关于联合收割机的视频,但我还是不知道该怎么做。
这是我的尝试
func combineHtml(url: String)-> AnyPublisher<String, NetworkServiceError>{
guard let safeUrl = URL(string: url) else {
return Fail(error: NetworkServiceError.badUrl).eraseToAnyPublisher()
}
let publisher = URLSession.shared
.dataTaskPublisher(for: safeUrl)
.tryMap{ result-> Data in
guard !result.data.isEmpty else{throw NetworkServiceError.networkFail("No data")}
return result.data
}
.tryMap{ data-> String in
guard let html = String(data: data, encoding: .utf8) else{
throw NetworkServiceError.networkFail("String serialization failed")
}
return html
}
// .mapError{ error-> NetworkServiceError in
// return NetworkServiceError.networkFail("error")
// }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
return publisher
}
我不确定我应该如何处理不同的错误:try 运算符应该抛出并且管道应该取消,这正是我想要的。但是,如果我不将错误映射到 NetworkServiceError,(注释代码)我应该更改我想避免的 return 类型。
我的错误处理一定有不正确的地方。
在 combine 中处理多个错误的最佳方法是什么?
我对这段代码不是很满意。
我设法解决了这个问题。
我将post相关部分代码,其余不变
.tryMap{ result-> String in
guard !result.data.isEmpty else{throw NetworkServiceError.networkFail("No data")}
guard let html = String(data: result.data, encoding: .utf8) else{
throw NetworkServiceError.networkFail("String serialization failed")
}
return html
}
.mapError{error-> NetworkServiceError in
if let customError = error as? NetworkServiceError{
return customError
}
return NetworkServiceError.networkFail(error.localizedDescription)
}
mapError 运算符是实现类型要求所必需的。在 tryMap 中,我们可以抛出所有需要的错误,因为我们将在 mapError 闭包中捕获它们
我决定将标准网络调用迁移到使用 combine 及其运算符的调用。
给定以下代码
enum NetworkServiceError: Error{
case badUrl
case networkFail(String)
}
func getHtml(from url: String, completion: @escaping (Result<String, NetworkServiceError>) -> ()) {
guard let url = URL(string: url) else {
completion(.failure(.badUrl))
return
}
URLSession.shared.dataTask(with: url) { (data, _, error) in
if let err = error{
completion(.failure(.networkFail(err.localizedDescription)))
return
}
guard let rawHtmlData = data else {
completion(.failure(.networkFail("No data")))
return
}
guard let html = String(data: rawHtmlData, encoding: .utf8) else {
completion(.failure(.networkFail("String serialization failed")))
return
}
completion(.success(html))
}
.resume()
}
我希望在 combine 对应物中有同样精确的错误处理。 老实说,尽管我看了很多关于联合收割机的视频,但我还是不知道该怎么做。 这是我的尝试
func combineHtml(url: String)-> AnyPublisher<String, NetworkServiceError>{
guard let safeUrl = URL(string: url) else {
return Fail(error: NetworkServiceError.badUrl).eraseToAnyPublisher()
}
let publisher = URLSession.shared
.dataTaskPublisher(for: safeUrl)
.tryMap{ result-> Data in
guard !result.data.isEmpty else{throw NetworkServiceError.networkFail("No data")}
return result.data
}
.tryMap{ data-> String in
guard let html = String(data: data, encoding: .utf8) else{
throw NetworkServiceError.networkFail("String serialization failed")
}
return html
}
// .mapError{ error-> NetworkServiceError in
// return NetworkServiceError.networkFail("error")
// }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
return publisher
}
我不确定我应该如何处理不同的错误:try 运算符应该抛出并且管道应该取消,这正是我想要的。但是,如果我不将错误映射到 NetworkServiceError,(注释代码)我应该更改我想避免的 return 类型。 我的错误处理一定有不正确的地方。
在 combine 中处理多个错误的最佳方法是什么? 我对这段代码不是很满意。
我设法解决了这个问题。 我将post相关部分代码,其余不变
.tryMap{ result-> String in
guard !result.data.isEmpty else{throw NetworkServiceError.networkFail("No data")}
guard let html = String(data: result.data, encoding: .utf8) else{
throw NetworkServiceError.networkFail("String serialization failed")
}
return html
}
.mapError{error-> NetworkServiceError in
if let customError = error as? NetworkServiceError{
return customError
}
return NetworkServiceError.networkFail(error.localizedDescription)
}
mapError 运算符是实现类型要求所必需的。在 tryMap 中,我们可以抛出所有需要的错误,因为我们将在 mapError 闭包中捕获它们