代码之家  ›  专栏  ›  技术社区  ›  coinhndp

防止观测错误完成并处理swift

  •  -1
  • coinhndp  · 技术社区  · 7 年前

    我有一个可观察到的(来自网络的请求),不希望在出现错误时将其处理掉

       enum MyError: Error {
            case notFound
            case unknown
        }
    

    我的网络请求使用Moya

    let registerRequest = didTapJoinButton.withLatestFrom(text.asObservable())
                .flatMapLatest { text in
                    provider.rx.request(API.register(text: text))
                }
                .flatMapLatest({ (response) -> Observable<Response> in
                    let statusCode = response.statusCode
    
                    if statusCode.isSuccessStatus() {
                        return Observable.just(response)
    
                    } else if statusCode.isNotFoundStatus() {
                        return Observable.error(MyError.notFound)
    
                    } else {
                        return Observable.error(MyError.unknown)
                    }
                })
                .materialize()
                .share(replay: 1)
    

    看起来很棒。我使用materialize()来防止在发生错误时处理observable

    订阅:(如果状态代码为200) 一切都很好,我得到了回应,流没有被处理

       registerEventRequest.subscribe(onNext: { (next) in
                print("NEXT: \(next)")
            }, onError: { (error) in
                print("ERRRRROR ME: \(error)")
            }, onCompleted: {
                print("Completed")
            }) {
                print("Disposed")
            }
    

    但如果状态码是404。我得到了预期的错误。但是,请查看控制台日志

    NEXT: error(notFound)
    Completed
    Disposed
    

    它跳到了我期待的下一个。但为什么它会抛出完整的和处置我的序列。

    我的问题是,它为什么要处理我的序列,以及我如何防止这种情况?

    1 回复  |  直到 7 年前
        1
  •  2
  •   Daniel T.    7 年前

    .materialize() 不 一种可以观察到的错误。当一个可观察对象发出错误时,它就完成了,而materialize仅仅将该错误转换为下一个事件。

    你需要把它具体化 第一个flatMapLatest用于防止错误转义flatMap闭包。

    此视频可能会有所帮助(注意 selectMany 与 flatMap ) https://channel9.msdn.com/Blogs/J.Van.Gogh/Reactive-Extensions-API-in-depth-SelectMany?term=select%20many&lang-en=true


    let registerRequest = didTapJoinButton.withLatestFrom(text.asObservable())
        .flatMapLatest { text in
            provider.rx.request(API.register(text: text))
                .materialize()
        }
        .map { (event) -> Event<Response> in
            switch event {
            case .next(let response) where response.statusCode.isNotFoundStatus():
                return Event.error(MyError.notFound)
    
            case .next(let response) where response.statusCode.isSuccessStatus() == false:
                return Event.error(MyError.unknown)
    
            default:
                return event
            }
        }
        .share(replay: 1)
    

    我搬家了 materialize() 它所属的位置,这样错误就不会打破链条。我也换掉了第二个 flatMapLatest 简单来说 map 因为没有必要做额外的工作。

    switch event {
    case .next(let response):
        let statusCode = response.statusCode
        if statusCode.isNotFoundStatus() {
            return Event.error(MyError.notFound)
        }
        else if statusCode.isSuccessStatus() {
            return event
        }
        else {
            return Event.error(MyError.unknown)
        }
    
    default:
        return event
    }
    

    但我认为我这样做更干净,因为它减少了闭包的圈复杂度。


    以下是处理评论中提出的问题的代码:

    extension ObservableType {
        func flatMapLatestT<T, U>(_ selector: @escaping (T) -> Observable<U>) -> Observable<Event<U>>
            where Self.E == Event<T>
        {
            return self.flatMapLatest { (event) -> Observable<Event<U>> in
                switch event {
                case .next(let element):
                    return selector(element).materialize()
                case .completed:
                    return .just(Event<U>.completed)
                case .error(let error):
                    return .just(Event<U>.error(error))
                }
            }
        }
    }
    

    https://gist.github.com/dtartaglia/d7b8d5c63cf0c91b85b629a419b98d7e

    推荐文章