.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