在 RxSwift 中重新启动可观察间隔的正确方法
Correct way to restart observable interval in RxSwift
在我的 OS X 状态栏应用程序中,我使用 interval
函数定期调用外部 api 并显示结果:
Observable<Int>
.interval(120.0, scheduler: MainScheduler.instance)
.startWith(-1) // to start immediately
.flatMapLatest(makeRequest) // makeRequest is (dummy: Int) -> Observable<SummaryResponse?>
.subscribeNext(setSummary)
.addDisposableTo(disposeBag)
但是,如果用户在此期间更改了首选项,我想 "restart" 这个间隔并立即进行新调用以反映更改(无需等待下一次调用)。
最好的方法是什么?
- 将 observable 存储为 属性 并将其设置为
nil
或对其调用 .dispose()
(或两者)并创建一个新的 observable ?
- 将
disposeBag
设置为 nil
并创建一个新的可观察对象 ?
- 还有其他方法吗?
您要找的是merge
。您有两个 Observable
,其中一个是 interval
,另一个代表偏好更改。你想 merge
将它们合二为一 Observable
与来自两者的元素,当它们出现时立即。
看起来像这样:
// this should really come from somewhere else in your app
let preferencesChanged = PublishSubject<Void>()
// the `map` is so that the element type goes from `Int` to `Void`
// since the `merge` requires that the element types match
let timer = Observable<Int>.timer(0, period: 3, scheduler: MainScheduler.instance).map { _ in () }
Observable.of(timer, preferencesChanged)
.merge()
.flatMapLatest(makeRequest)
.subscribeNext(setSummary)
.addDisposableTo(disposeBag)
另请注意我是如何使用 timer
而不是 interval
,因为它允许我们指定首次触发的时间以及后续触发的时间段。这样,您就不需要 startWith
。但是,这两种方法都有效。这是一个偏好问题。
还有一点要注意。这超出了您的问题范围(也许您为了问题而保持简单)但是您应该考虑将结果保留为 Observable 而不是 subscribeNext(setSummary)
,而不是 bindTo
或 drive
UI 或 DB(或任何 "summary")。
在我的 OS X 状态栏应用程序中,我使用 interval
函数定期调用外部 api 并显示结果:
Observable<Int>
.interval(120.0, scheduler: MainScheduler.instance)
.startWith(-1) // to start immediately
.flatMapLatest(makeRequest) // makeRequest is (dummy: Int) -> Observable<SummaryResponse?>
.subscribeNext(setSummary)
.addDisposableTo(disposeBag)
但是,如果用户在此期间更改了首选项,我想 "restart" 这个间隔并立即进行新调用以反映更改(无需等待下一次调用)。
最好的方法是什么?
- 将 observable 存储为 属性 并将其设置为
nil
或对其调用.dispose()
(或两者)并创建一个新的 observable ? - 将
disposeBag
设置为nil
并创建一个新的可观察对象 ? - 还有其他方法吗?
您要找的是merge
。您有两个 Observable
,其中一个是 interval
,另一个代表偏好更改。你想 merge
将它们合二为一 Observable
与来自两者的元素,当它们出现时立即。
看起来像这样:
// this should really come from somewhere else in your app
let preferencesChanged = PublishSubject<Void>()
// the `map` is so that the element type goes from `Int` to `Void`
// since the `merge` requires that the element types match
let timer = Observable<Int>.timer(0, period: 3, scheduler: MainScheduler.instance).map { _ in () }
Observable.of(timer, preferencesChanged)
.merge()
.flatMapLatest(makeRequest)
.subscribeNext(setSummary)
.addDisposableTo(disposeBag)
另请注意我是如何使用 timer
而不是 interval
,因为它允许我们指定首次触发的时间以及后续触发的时间段。这样,您就不需要 startWith
。但是,这两种方法都有效。这是一个偏好问题。
还有一点要注意。这超出了您的问题范围(也许您为了问题而保持简单)但是您应该考虑将结果保留为 Observable 而不是 subscribeNext(setSummary)
,而不是 bindTo
或 drive
UI 或 DB(或任何 "summary")。