第二次订阅来自 BehaviorSubject 的共享映射不执行
Second subscription to a shared mapping from BehaviorSubject does not execute
当我从 BehaviorSubject
实例 (t
) 订阅共享映射时,仅执行第一个订阅。
当原始BehaviorSubject
(obj
)发出第二个值时,仅打印最新值,并执行两个订阅。
让我们检查我的代码
const obj = new Rx.BehaviorSubject(1)
obj.subscribe(console.log)
const t = obj.map(u => {
console.log("mapped")
return u * 10
}).share()
t.subscribe(x => console.log("subscribe 1 " + x))
t.subscribe(x => console.log("subscribe 2 " + x))
//with the following line un-commented, both subscriptions print out new value
//obj.next(2)
我的预期结果是
1
mapped
subscribe 1 10
subscribe 2 10
但实际结果是
1
mapped
subscribe 1 10
抱歉这个幼稚的问题。有谁能给我解释一下吗?
非常感谢
任何运算符(包括 share
)实际上都会创建一个新的 Sub-Observable,它有自己的 share/replay-properties 与 source-observable 分离。
所以要得到你的结果,你应该使用 publishReplay(1)
而不是 share()
。
(对于 publishReplay
,您当然必须使用 refCount()
或 connect()
)
const obj = new Rx.BehaviorSubject(1)
obj.subscribe(console.log)
const t = obj.map(u => {
console.log("mapped")
return u * 10
}).publishReplay(1)
.refCount();
t.subscribe(x => console.log("subscribe 1 " + x))
t.subscribe(x => console.log("subscribe 2 " + x))
//with the following line un-commented, both subscriptions print out new value
//obj.next(2)
<script src="https://unpkg.com/rxjs/bundles/Rx.min.js"></script>
在您的示例中,您有两个主题:
obj
中的BehaviorSubject
。
Subject
实例在 .share()
.
请记住,BehaviorSubject
仅在您订阅它时才会发出其缓存值 。
第一个观察者 obj.subscribe(console.log)
直接订阅了 BehaviorSubject
。这会打印 1
.
然后创建以 share()
运算符结尾的链 t
。
现在您用 t.subscribe
订阅了 t
。这意味着你订阅了 share()
里面的 Subject
并且因为这是它的第一个观察者它需要订阅它的源 Observable(它又到达源 BehaviorSubject
发出它的缓存值) .请注意 share()
只是将 multicast()
运算符与 refCount()
.
一起使用的快捷方式
最后一行你再次订阅 t.subscribe
。就像之前订阅 share()
里面的 Subject
一样。但是 share()
已经订阅了它的源 Observable,所以它 不会再订阅 。这就是多播和 multicast()
运算符的意义所在。
这就是为什么您不会看到任何 subscribe 2 10
并且您甚至不会看到 mapped
被打印两次的原因。您订阅的是 share()
中的 Subject
,而不是来源 BehaviorSubject
.
当我从 BehaviorSubject
实例 (t
) 订阅共享映射时,仅执行第一个订阅。
当原始BehaviorSubject
(obj
)发出第二个值时,仅打印最新值,并执行两个订阅。
让我们检查我的代码
const obj = new Rx.BehaviorSubject(1)
obj.subscribe(console.log)
const t = obj.map(u => {
console.log("mapped")
return u * 10
}).share()
t.subscribe(x => console.log("subscribe 1 " + x))
t.subscribe(x => console.log("subscribe 2 " + x))
//with the following line un-commented, both subscriptions print out new value
//obj.next(2)
我的预期结果是
1
mapped
subscribe 1 10
subscribe 2 10
但实际结果是
1
mapped
subscribe 1 10
抱歉这个幼稚的问题。有谁能给我解释一下吗?
非常感谢
任何运算符(包括 share
)实际上都会创建一个新的 Sub-Observable,它有自己的 share/replay-properties 与 source-observable 分离。
所以要得到你的结果,你应该使用 publishReplay(1)
而不是 share()
。
(对于 publishReplay
,您当然必须使用 refCount()
或 connect()
)
const obj = new Rx.BehaviorSubject(1)
obj.subscribe(console.log)
const t = obj.map(u => {
console.log("mapped")
return u * 10
}).publishReplay(1)
.refCount();
t.subscribe(x => console.log("subscribe 1 " + x))
t.subscribe(x => console.log("subscribe 2 " + x))
//with the following line un-commented, both subscriptions print out new value
//obj.next(2)
<script src="https://unpkg.com/rxjs/bundles/Rx.min.js"></script>
在您的示例中,您有两个主题:
obj
中的BehaviorSubject
。Subject
实例在.share()
.
请记住,BehaviorSubject
仅在您订阅它时才会发出其缓存值 。
第一个观察者 obj.subscribe(console.log)
直接订阅了 BehaviorSubject
。这会打印 1
.
然后创建以 share()
运算符结尾的链 t
。
现在您用 t.subscribe
订阅了 t
。这意味着你订阅了 share()
里面的 Subject
并且因为这是它的第一个观察者它需要订阅它的源 Observable(它又到达源 BehaviorSubject
发出它的缓存值) .请注意 share()
只是将 multicast()
运算符与 refCount()
.
最后一行你再次订阅 t.subscribe
。就像之前订阅 share()
里面的 Subject
一样。但是 share()
已经订阅了它的源 Observable,所以它 不会再订阅 。这就是多播和 multicast()
运算符的意义所在。
这就是为什么您不会看到任何 subscribe 2 10
并且您甚至不会看到 mapped
被打印两次的原因。您订阅的是 share()
中的 Subject
,而不是来源 BehaviorSubject
.