无法在网络调用中返回可观察到的 customError
Posted
技术标签:
【中文标题】无法在网络调用中返回可观察到的 customError【英文标题】:can't return observable of customError in network call 【发布时间】:2018-10-15 11:16:54 【问题描述】:我想使用 catchError 将我的错误恢复为自定义类型。 起初,我希望我的网络层返回 Observable,然后在 ViewModel 中订阅了 .OnNext、.OnError、.OnCompleted 事件,但我不知道应该如何处理诸如 4xx、5xx 网络状态码之类的错误,然后,他们返回我的自定义错误对象!
我的登录视图模型:
func getAccessToken()
let network = NetworkRequest()
network.logInRequest(tokenType: .guest, token: "cce577f6021608", secondKey: "09128147040", client: "cce577f6021608bc31424d209cbf5120c3683191").subscribe(onNext: loginData in
self.token.onNext(loginData.access_token)
, onError: error in
print("The Error is: \(error.localizedDescription)")
, onCompleted:
print("Its Completed")
).disposed(by: bag)
我的网络层函数:
class NetworkRequest: NSObject
var rxProvider: MoyaProvider<WebServiceAPIs>
override init()
rxProvider = MoyaProvider<WebServiceAPIs>( plugins: [ NetworkLoggerPlugin(verbose:true) ])
func logInRequest(tokenType: accessTokenTypeEnum, token: String, secondKey: String, client: String) -> Observable<LoginModel>
return rxProvider.rx
.request(WebServiceAPIs.getAccessToken(tokenType: tokenType.rawValue, token: token, secondKey: secondKey, client: client))
.filterSuccessfulStatusCodes()
.catchError( error -> Observable<NetworkError> in
return //Observable.just() => I want to return a custom network error as obserable
)
.map(LoginModel.self, atKeyPath: nil, using: JSONDecoder(), failsOnEmptyData: true).asObservable()
感谢您的帮助
【问题讨论】:
【参考方案1】:根据我的经验,'.materialize()' 运算符是处理 HTTP 错误的完美解决方案。 您将获得一个单独的包装器事件,而不是单独的成功和错误事件,其中嵌套了成功或错误。
【讨论】:
在adamborek.com/how-to-handle-errors-in-rxswift 页面上搜索“materialize” - 有一个非常适合您的案例的示例(恕我直言)。【参考方案2】:Moya 在错误块中返回 MoyaError 枚举,您可以通过使用打开 MoyaError 的开关提取错误类型然后使用 statusCode 转换为 NetworkError 枚举来处理它
func logInRequest(tokenType: accessTokenTypeEnum, token: String, secondKey: String, client: String) -> Observable<LoginModel>
return sharedProvider.rx
.request(WebServiceAPIs.getAccessToken(tokenType: tokenType.rawValue, token: token, secondKey: secondKey, client: client))
.filterSuccessfulStatusCodes()
.catchError( [weak self] error -> Observable<NetworkError> in
guard let strongSelf = self else return Observable.empty()
if let moyaError = error as? MoyaError
let networkError = self?.createNetworkError(from: moyaError)
return Observable.error(networkError)
else
return Observable.error(NetworkError.somethingWentWrong(error.localizedDescription))
)
.map(LoginModel.self, atKeyPath: nil, using: JSONDecoder(), failsOnEmptyData: true).asObservable()
func createNetworkError(from moyaError: MoyaError) -> NetowrkError
switch moyaError
case .statusCode(let response):
return NetworkError.mapError(statusCode: response.statusCode)
case .underlying(let error, let response):
if let response = response
return NetworkError.mapError(statusCode: response.statusCode)
else
if let nsError = error as? NSError
return NetworkError.mapError(statusCode: nsError.code)
else
return NetworkError.notConnectedToInternet
default:
return NetworkError.somethingWentWrong("Something went wrong. Please try again.")
您可以创建自定义 NetworkError 枚举,如下所示,它将 statusCode 映射到自定义 NetworkError 枚举值。它将具有 errorDescription var,它将返回自定义描述以显示在错误视图中
enum NetworkError: Swift.Error
case unauthorized
case serviceNotAvailable
case notConnectedToInternet
case somethingWentWrong(String)
static func mapError(statusCode: Int) -> NetworkError
switch statusCode
case 401:
return .unauthorized
case 501:
return .serviceNotAvailable
case -1009:
return .notConnectedToInternet
default:
return .somethingWentWrong("Something went wrong. Please try again.")
var errorDescription: String
switch self
case .unauthorized:
return "Unauthorised response from the server"
case .notConnectedToInternet:
return "Not connected to Internet"
case .serviceNotAvailable:
return "Service is not available. Try later"
case .somethingWentWrong(let errorMessage):
return errorMessage
【讨论】:
以上是关于无法在网络调用中返回可观察到的 customError的主要内容,如果未能解决你的问题,请参考以下文章
在 ViewController 中可观察到的单元测试 RxSwift