gpt4 book ai didi

swift - 防止 Observabe.error 完成并快速处理

转载 作者:行者123 更新时间:2023-11-28 11:40:00 25 4
gpt4 key购买 nike

我有一个可观察的(来自网络的请求)并且不希望在出现错误时处理它

我的自定义错误

   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

它跳转到了我预期的 NEXT。但为什么它会抛出 complete 并处理我的序列。

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

最佳答案

.materialize() 不会防止 observable 在发生错误时被处置。当 Observable 发出错误时,它就完成了,物化只是将该错误转换为下一个事件。

您需要将物化放在第一个 flatMapLatest 中,以防止错误从 flatMap 闭包中逃脱。

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


这是另一种组合 Observable 的方法:

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语句也可以这样写:

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

关于swift - 防止 Observabe.error 完成并快速处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53944423/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com