【问题标题】:How to defensively create Rx Observables and avoid race conditions?如何防御性地创建 Rx Observables 并避免竞争条件?
【发布时间】:2017-02-16 07:46:33
【问题描述】:

我正在寻找一个奇怪的边缘情况,其中目录中的文件列表没有显示 0...2 个文件的结果,但对于 3...n 个文件工作正常。

原来可观察到的原始序列运行良好。但是我在一个订阅者中使用了PublishSubject 来传递更改的效果。据报道,所有这些都发生在主队列上,但似乎PublishSubject 在它拥有订阅者之前就获得了馈送值。 (由于没有重播,订阅者不会知道。)

所以所有组件的设置(来源——中继订阅者——消费订阅者)似乎都引入了时间作为一个问题。

奇怪的观察:

  • 如果我将原来的Observable 变成Driver,一切正常。
  • 如果我在原始链中的某处插入.observeOn(MainScheduler.instance)(在中继订户之前),一切正常。尽管我可以通过在映射操作中使用断点看到映射已经发生在 com.apple.main-queue (serial) 上。
  • 如果我在来源或订阅者的代码中使用.subscribeOn(MainScheduler.instance),我仍然会遇到问题。 (可能是因为一开始它只影响中继订阅者,后来为时已晚。)

现在我不明白如何防御性地处理此类问题。

看来PublishSubject 可能不适合这种情况。但是为什么在主队列上观察会改善这种情况呢?

您何时应该(防御性地)指定在主队列上运行的可观察序列在创建/生产时?(同样,这可能是一个实用的修复,但它只是似乎意外地解决了问题。)

或者,换句话说,你应该在什么时候假设消费者的代码没有及时发生,即在订阅设置时?

我无法判断将事件从输入序列中继到PublishSubject 会导致麻烦。这是不可感知的。让我很困惑如何避免这样的错误。

【问题讨论】:

  • 你在谈论热与冷的 observables (github.com/Reactive-Extensions/RxJS/blob/master/doc/…)。问题不在于线程或/和时间,而在于您在有人订阅 observable 之前发出项目。想到的两种解决方案:a)仅在订阅后发出信号(冷可观察)或 b)向链添加重播(reactivex.io/documentation/operators/replay.html)
  • 是的,归根结底。通过PublishSubject 订阅cold observable 并发出通知事件似乎使我最终消费的东西“热”了。我在自己的代码中没有注意到这一点;我如何让其他人明显区分热/冷?人们是否遵守命名约定,或者您在使用信号时需要先感到惊讶?

标签: swift concurrency rx-swift defensive-programming


【解决方案1】:

你需要了解observeOn和subscribeOn的区别以及Driver序列的属性。

observeOn 影响观察块,即您处理发射值的位置,例如

someObservable
.subscribe(onNext: { /* this is an example of observation block */ })

subscribeOn 影响订阅块中的调度程序,即 产生值的地方,例如

Observable<Int>.create { /* this is an example of subscription block */ }

驱动程序

驱动程序是一种特殊类型的可观察序列,具有一些属性。

  • 驱动程序永远不会失败,即没有 onError 事件
  • 驱动程序将.observeOn(MainScheduler.instance) 添加到序列中
  • 驱动程序使用.share(replay: 1, scope: .whileConnected) 运算符共享序列

考虑到最后两个,你可以从 observable 做你自己的驱动程序:

someObservable
.observeOn(MainScheduler.instance)
.share(replay: 1, scope: .whileConnected)

这就是你的问题可能想要做的。

【讨论】:

  • 谢谢 -- 4 年后,我对那部分有了更好的理解。可悲的是,我不记得我究竟是如何介绍这个问题的。可能是订阅在 BG 队列上运行,但这个细节并不明显?无论如何,享受接受答案的积分:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-30
  • 2010-09-25
相关资源
最近更新 更多