在网络通话中无法返回可观察到的customError

时间:2018-10-15 11:16:54

标签: ios swift rx-swift moya

我想使用catchError来取回我的错误作为自定义类型。 首先,我希望我的网络层返回Observable,然后在ViewModel中为.OnNext,.OnError,.OnCompleted事件订阅它,但是我不知道如何处理诸如4xx,5xx网络状态代码之类的错误,然后,他们返回我的自定义错误对象!

我的登录ViewModel:

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()
    }

}

感谢您的帮助

2 个答案:

答案 0 :(得分:0)

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
        }
    }
}

答案 1 :(得分:0)

根据我的经验,' .materialize()'运算符是处理HTTP错误的理想解决方案。 除了获得成功或错误的单独事件外,您还可以获得一个嵌套了成功或错误的包装事件。