我有一个可观察到的(来自网络的请求),并且不想在遇到错误时将其丢弃
我的自定义错误
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()来防止将可观察的对象置于错误状态
订阅:(如果状态码为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。但是为什么它会完整地处理我的序列。
我的问题是为什么它要处理我的序列以及如何防止这种情况发生?
答案 0 :(得分:1)
.materialize()
不能防止被错误观察到。当Observable发出错误时,它完成并且具体化只是将错误转换为下一个事件。
您需要将实体化放入第一个flatMapLatest中,以防止错误转义flatMap闭包。
该视频可能会有所帮助(注意selectMany
与flatMap
相同)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