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

RxSwift+Alamofire custom mapper error handling

RxSwift 还有一个关于错误处理的问题:

我是这样使用Alamofire+RxAlamofire的:

SessionManager.default.rx.responseJSON(.post, url, parameters:params)

示例:

func login() -> Observable<Int> {
    let urlString = ...
    let params = ...
    return SessionManager.default.rx.responseJSON(.post, url, parameters:params)
        .rxJsonDefaultResponse()
        .map({ (data) in
            data["clientId"] as! Int
        })
}
....

extension ObservableType where Element == (HTTPURLResponse, Any) {

    func rxJsonDefaultResponse() -> Observable<Dictionary<String, Any>> {

        return self.asObservable().map { data -> Dictionary<String, Any> in

            if... //error chechings
                    throw NSError(domain: ..,
                                  code: ...,
                                  userInfo: ...)
            }
            ...
            return json
        }
    }
}

使用:

loginBtn.rx.tap
.flatMap{ _ in
    provider.login()
}.subscribe(onNext: { id in
       ... 
    }, onError: { (er) in
        ErrorPresentationHelper.showErrorAlert(for: er)
    })
.disposed(by: bag)

因此,如果发生错误,一切都会按预期进行:显示错误警报并 'loginBtn.rx.tap' 已处理,但我需要它仍然存在,如果我想使用 onError 块,我的策略是什么?

您可以在 rxSwift 中使用 materialize 函数。它会将任何 Observable 转换为其事件的 Observable。这样你就会听到 Observable<Event<Int>> 而不是 Observable<Int>。从平面图抛出的任何错误都将在订阅块的 onNext 中作为错误事件被捕获,并可以在那里进行处理。而且您的订阅仍然有效。示例代码如下。

        button.rx.tap.flatMap { _ in
            return Observable.just(0)
            .flatMap { _ -> Observable<Int> in
                provider.login()
            }.materialize()
        }.subscribe(onNext: { event in
            switch event {
            case .next:
                if let value = event.element {
                    print(value) //You will be getting your value here
                }
            case .error:
                if let error = event.error {
                    print(error.localizedDescription) //You will be getting your captured error here
                }
            case .completed:
                print("Subscription completed")
            }
        }) {
            print("Subscription disposed")
        }.disposed(by: disposeBag)

希望对您有所帮助。您可以签出实现扩展 here.