将 Moya 响应错误转换为定义的类型

Posted

技术标签:

【中文标题】将 Moya 响应错误转换为定义的类型【英文标题】:Casting Moya Response error to defined type 【发布时间】:2019-08-30 10:19:52 【问题描述】:

我正在使用 RxMoya 进行网络调用并扩展 PremitiveSequence 和 Response 以处理返回的错误。我声明了一个网络错误结构,我可以使用它来获取所有错误详细信息,并通过 BaseResponse 模型传递错误消息。这是我的 NetworkingError 结构

public struct NetworkingError: Error 
    let httpResponse: HTTPURLResponse?
    let networkData: Data?
    let baseError: Error

对于我的编码,我将原始序列扩展如下

公共扩展 PrimitiveSequence 其中 TraitType == SingleTrait,

ElementType == Response 

    func mapObject<T: Codable>(_ type: T.Type, path: String? = nil) -> Single<T> 
        return flatMap  response -> Single<T> in
            return Single.just(try response.mapObject(type, path: path))
        
    

    func mapArray<T: Codable>(_ type: T.Type, path: String? = nil) -> Single<[T]> 
        return flatMap  response -> Single<[T]> in
            return Single.just(try response.mapArray(type, path: path))
        
    

    func filterSuccess() -> Single<E> 
        return flatMap  (response) -> Single<E> in
            if 200 ... 299 ~= response.statusCode 
                return Single.just(response)
            

            print("THIS ERROR JSON jsonObject2 xx mm \(response.data)")

            do 
                let jsonObject2 = try JSONSerialization.jsonObject(with: response.getJsonData(), options: .allowFragments)
                print("THIS ERROR JSON jsonObject2 xx \(jsonObject2)")
                let jsonObject = try JSONSerialization.jsonObject(with: response.getJsonData(), options: .allowFragments) as? NetworkingError

                print("THIS ERROR JSON  xx \(jsonObject)")
                return Single.error(jsonObject ?? NetworkingError.self as! Error)
            
        
    

如果我在这里运行此代码,应用程序会崩溃 return Single.error(jsonObject ?? NetworkingError.self as! Error)

在我的代码中,我传递的数据类似于

func postVerifyApp(challenge: Int, identifier: String) -> Observable<AuthResponse> 

        return provider.rx.request(.postVerifyApp(challenge: challenge, identifier: identifier))

            .filterSuccess()
            .mapObject(AuthResponse.self)
            .asObservable()
            .flatMap( authResponse -> Observable<AuthResponse> in
                return self.sendTokenToServer(authResponse)
            )
    

然后我正在像这样在我的演示者类中使用它

func postVerifyApp(challenge: Int, identifier: String) 
        view?.setProgress(enabled: true)
        source.postVerifyApp(challenge: challenge, identifier: identifier)
            .retry(.delayed(maxCount: 2, time: 2.5), shouldRetry: networkRetryPredicate)
            .asSingle()
            .subscribe(onSuccess:  [weak self] response in
                guard let presenter = self, let view = presenter.view else return
                view.setProgress(enabled: false)
                log(response, .json)
                guard let data = response.data else 
                    return 

                view.showVerifySuccess()
                , onError:  [weak self] error in
                    guard let presenter = self, let view = presenter.view else return
                    print("MESSAGE X \(error.localizedDescription)")
                    if let error = error as? NetworkingError 
                        print("MESSAGE X httpResponse \(error.httpResponse)")
                    
                    view.setProgress(enabled: false)

            ).disposed(by: disposeBag)
    

我希望能够传递此错误并提取错误消息并将其传递给控制台。

这是我的基本模型的样子

struct ResponseBase<T: Codable>: Codable 
    var error: Bool?
    var message: String?
    var data: T

    var isSucessful: Bool 
        return error == false
    


【问题讨论】:

【参考方案1】:

用于构造 Single.error 的表达式不能转换为 Error。首先,您尝试将 jsonObject(字典)转换为错误。在右侧,在 ifNull 表达式中,您尝试将元类型 (Networking.Type) 转换为错误。

要解决您的投射问题,您可以使用修改后的 NetworkingError。

public struct NetworkingError: Error 

    let httpResponse: HTTPURLResponse?
    let networkData: Data?
    let baseError: MoyaError

    init(_ response:Response) 
        self.baseError = MoyaError.statusCode(response)
        self.httpResponse = response.response
        self.networkData = response.data
    

    func getLocalizedDescription() -> String 

       return self.baseError.localizedDescription
    

有了这个,修改 filterSuccess 中的闭包来创建 NetworkingError 对象,将 Response 传递给它,就像这样:

func filterSuccess() -> Single<E> 
    return flatMap 
        (response) -> Single<E> in
        if 200 ... 299 ~= response.statusCode 
           return Single.just(response)
         else 
           let netError = NetworkingError(response)
           return Single.error(netError)
        
    

我鼓励你看看 MoyaError 的定义

【讨论】:

以上是关于将 Moya 响应错误转换为定义的类型的主要内容,如果未能解决你的问题,请参考以下文章

如何在不发送请求的情况下拦截 Moya 请求并返回失败响应

将错误响应转换为特定模型 - 斩波器颤振

Dojo.js AMD 加载程序 - 类型错误:无法将未定义转换为对象

错误:在 c 中转换用户定义的数据类型

Swift 解析 JSON 时出现问题:无法将“__NSCFDictionary”类型的值转换为“NSArray”错误

Moya 构建错误