RXSwift: поймать ошибку, не испуская элемент из потока - PullRequest
0 голосов
/ 29 ноября 2018

В конечном итоге мне нужен способ отлавливать ошибки RXSwift, не отправляя другой элемент в поток, это не представляется возможным с текущими операторами RX.

Вот как теперь работает мое приложение:

У меня есть 3 уровня:

  • Сервисный уровень
  • Локальный уровень данных
  • Удаленный уровень данных

Сервисный уровень действует какмост между локальным и удаленным уровнями и вызывается непосредственно кодом пользовательского интерфейса.

Для каждой функции, предоставляемой на уровне обслуживания, например, getData() -> Observable<String> Мне нужно сделать следующее:

  • Получитьлокальные данные и запуск отсчета тикера от 0 и выше каждую секунду
  • Получение данных от удаленной службы
  • Тикер должен завершиться только после завершения удаленной службы
  • Еслилокальная служба возвращает ошибку, она должна игнорироваться и не отправляться
  • Когда удаленная служба завершает работу, обновите локальные данные новыми данными, если таковые имеются

Я получил этодалеко в игрераунд:

Служба локальных данных:

let localService = Observable<String>.create { (observer) -> Disposable in
    observer.onNext("Local result")
    observer.onCompleted()
    return Disposables.create()
}.observeOn(MainScheduler.instance)

Служба удаленных данных:

let remoteService = Observable<String>.create { (observer) -> Disposable in
    observer.onNext("Remote result")
    observer.onCompleted()
    return Disposables.create()
}.observeOn(MainScheduler.instance).delay(5, scheduler: MainScheduler.instance)

Служба обновления базы данных:

let databaseUpdaterService = Observable<Void>.empty().observeOn(MainScheduler.instance).delay(2, scheduler: MainScheduler.instance)
let remoteAndDatabaseService = remoteService.do(onNext: { (value) in
    print("Database updating")
    _ = databaseUpdaterService.subscribe(onCompleted: {
        print("Database updated")
    })
})

Тикер времени:

let ticker = Observable<Int>.interval(1, scheduler: MainScheduler.instance).do(onNext: { (tick) in
    print("Ticker event: \(tick) seconds")
}).takeUntil(remoteService)

Объединенный сервис:

let mergedService = Observable<String>.merge([localService, remoteAndDatabaseService])

Запуск тикера:

print("Ticker start")
_ = ticker.subscribe(onError: { (error) in
    print("Ticker error")
}, onCompleted: {
    print("Ticker completed")
}, onDisposed: {
    print("Ticker disposed")
})

Запуск сервиса:

print("Service start")
_ = mergedService.subscribe(onNext: { (value) in
    print("Service value: \(value)")
}, onError: { (error) in
    print(error.localizedDescription)
}, onCompleted: {
    print("Service completed")
}, onDisposed: {
    print("Service disposed")
})

Для счастливого пути это работает отлично.

Однако, в случае, когда localService вызывает onError (если локальный объект не существует, например), объединенный поток завершается.

Я бы хотел, чтобы ошибка была проглочена и ничего не было отправлено потоком для localService.

В настоящее время операторы catch вынуждают вас испускать другой объект, вместо того чтобы молча отказывать.

Заранее спасибо за помощь.

Ответы [ 2 ]

0 голосов
/ 30 ноября 2018

Если вы не хотите вносить всю библиотеку RxSwiftExt только для одной вещи, вы можете использовать .catchError { _ in Observable.empty() }, которая сожрет ошибку и выдаст полное событие.

Другой вариант - .catchError { _ in Observable.never() }, которыйбудет есть ошибку, а затем ничего не излучать.

0 голосов
/ 29 ноября 2018

Nevermind,

Похоже, RxSwiftExt имеет следующий метод, который работает для моего случая использования: catchErrorJustComplete() -> Observable<E>

...