为什么在 `withLatestFrom` 中的可观察对象上使用 `share` 运算符会导致在其中一个订阅中跳过某个事件?
Why using the `share` operator on the observable in `withLatestFrom` will result in an event being skipped in one of the subscriptions?
使用以下代码:
let stringSubject = BehaviorSubject<String?>(value: nil).share()
let intSubject = BehaviorSubject<Int?>(value: nil)
let intObservable = intSubject.compactMap { [=10=] }
let resultingSequence = intObservable
.take(1)
.withLatestFrom(stringSubject) { ([=10=], ) }
.filter { [=10=].1 == nil }
.map { [=10=].0 }
let subscriptionB = resultingSequence
.skip(1)
.subscribe(onNext: { print("Subscription B: \([=10=])") })
let subscriptionA = resultingSequence
.subscribe(onNext: { print("Subscription A: \([=10=])") })
intSubject.onNext(1)
print("Finished")
我期待的是事件 1
将由 subscriptionA
处理,即打印如下内容:
Subscription A: 1
Finished
但在实际结果中没有打印任何内容,即
Finished
但是,如果删除 stringSubject
的 share()
,或者将 share()
添加到 resultingSequence
声明的末尾,则预期结果将是印刷。
这背后的原因是什么?
因为你的resultingSequence
没有分享,所以stringSubject
有两个订阅。 .share()
有一个参数 replay
定义将向未来的订阅者重放多少先前发出的序列元素,此参数的默认值为 0。
因此,当您执行 stringSubject.share()
时,第一个订阅将收到初始值 (nil),但任何后续订阅都不会收到任何值,因为 stringSubject
现在已发出其初始值并且您已告知它向新订阅者重播 0 个先前发出的元素。
将 .share()
更改为 .share(replay: 1)
也会提供您想要的输出,因为已经发出的初始值将重播给任何新订阅者。
使用以下代码:
let stringSubject = BehaviorSubject<String?>(value: nil).share()
let intSubject = BehaviorSubject<Int?>(value: nil)
let intObservable = intSubject.compactMap { [=10=] }
let resultingSequence = intObservable
.take(1)
.withLatestFrom(stringSubject) { ([=10=], ) }
.filter { [=10=].1 == nil }
.map { [=10=].0 }
let subscriptionB = resultingSequence
.skip(1)
.subscribe(onNext: { print("Subscription B: \([=10=])") })
let subscriptionA = resultingSequence
.subscribe(onNext: { print("Subscription A: \([=10=])") })
intSubject.onNext(1)
print("Finished")
我期待的是事件 1
将由 subscriptionA
处理,即打印如下内容:
Subscription A: 1
Finished
但在实际结果中没有打印任何内容,即
Finished
但是,如果删除 stringSubject
的 share()
,或者将 share()
添加到 resultingSequence
声明的末尾,则预期结果将是印刷。
这背后的原因是什么?
因为你的resultingSequence
没有分享,所以stringSubject
有两个订阅。 .share()
有一个参数 replay
定义将向未来的订阅者重放多少先前发出的序列元素,此参数的默认值为 0。
因此,当您执行 stringSubject.share()
时,第一个订阅将收到初始值 (nil),但任何后续订阅都不会收到任何值,因为 stringSubject
现在已发出其初始值并且您已告知它向新订阅者重播 0 个先前发出的元素。
将 .share()
更改为 .share(replay: 1)
也会提供您想要的输出,因为已经发出的初始值将重播给任何新订阅者。