使用 Moya + RxSwift 处理自定义错误响应

Posted

技术标签:

【中文标题】使用 Moya + RxSwift 处理自定义错误响应【英文标题】:Custom Error Response Handling with Moya + RxSwift 【发布时间】:2017-01-04 05:41:04 【问题描述】:

我在 ios 应用程序中使用 Moya 和 RxSwift 进行联网,我希望能够在我的 Observers 收到对 onError 的调用时使用我的 API 的自定义错误响应。

API 始终以以下 JSON 格式返回错误响应:


   "error": 
      "message": "Error message goes here",
      "code": "String error code"
   

目标是实现类似于以下代码sn-p的东西,其中onError中传递的错误是我自定义的错误类型而不是Moya.Error类型:

observable
    .subscribe(
        onNext:  response in
            // Do typical onNext stuff
        ,
        onError:  error in
            // Get and consume my custom error type here:
            let customError = error as! MyCustomErrorModel
            print("My API's error message: \(customError.error?.message)")
            print("My API's error code: \(customError.error?.code)")
        )

我能够使用自定义PluginType(粘贴在下面,来自this SO question)成功拦截这些错误并将其反序列化到我的自定义错误模型中,但我不知道如何最终将这些模型传递给@ 987654329@。

import Foundation
import Moya
import ObjectMapper
import Result

struct CustomAPIErrorPlugin: PluginType 

// Called immediately before a request is sent over the network (or stubbed).
func willSendRequest(request: RequestType, target: TargetType)  

// Called after a response has been received, but before the MoyaProvider has invoked its completion handler.
func didReceiveResponse(result: Result<Moya.Response, Moya.Error>, target: TargetType) 
    let responseJSON: AnyObject
    if let response = result.value 
        do 
            responseJSON = try response.mapJSON()
            if let errorResponse = Mapper<MyCustomErrorModel>().map(responseJSON) 
                print("Custom error code from server: \(errorResponse.error?.code)")
            
         catch 
            print("Failure to parse JSON response")
        
     else 
        print("Network Error = \(result.error)")
    

【问题讨论】:

【参考方案1】:

我建议扩展 ObservableType,因为当我们谈论处理 api 错误响应时,这最终是最干净的解决方案。如下所示(未测试...)

extension ObservableType where E == Response 
  func filterSuccess() -> Observable<E> 
    return flatMap  (response) -> Observable<E> in
        if 200 ... 299 ~= response.statusCode 
            return Observable.just(response)
        

        if let errorJson = response.data.toJson(), 
           let error = Mapper<MyCustomErrorModel>().map(errorJson) 
            return Observable.error(error)
        

        // Its an error and can't decode error details from server, push generic message
        let genericError = MyCustomErrorModel.genericError(code: response.statusCode, message: "Unknown Error")
        return Observable.error(genericError)
    

这就是你使用它的方式

provider.request(.test)
        .filterSuccess()
        .mapJSON()
        .subscribe  [unowned self] e in
            switch e 
            case .next(let json as JSON):
            case .error(let error as MyCustomErrorModel):
            // Handle your custom error here
            default: break
            
    .disposed(by: disposeBag)

【讨论】:

以上是关于使用 Moya + RxSwift 处理自定义错误响应的主要内容,如果未能解决你的问题,请参考以下文章

moya 与 RxSwift 使用

RxSwift+Alamofire 自定义映射器错误处理

RxSwift 和 Moya 同步请求

RxSwift 映射问题

如何使用 Moya RxSwift 合并 REST 数组

RxSwift+Moya+Moya_ObjectMapper+MJRefresh,刷新失败?