为什么共享Observable会在首个订阅完成时触发重新订阅?
这个重订阅现象是share()操作符的内置重置逻辑和代码中的延迟触发共同导致的,具体拆解如下:
1. share()的多播与重置规则
share()本质是引用计数型多播:
- 当订阅者数量从0变为1时,自动订阅上游冷Observable,开始发射值,所有后续订阅共享同一条上游数据流
- 当所有订阅者都退订(或上游发射完成/错误通知导致所有订阅自动结束),引用计数归0后,
share()会清空内部的多播状态,后续再有新订阅时会重新订阅上游,触发上游冷Observable重新执行
2. 代码执行时间线拆解
我们按时间线走完整流程就能清晰看到重订阅的触发点:
- t=0时刻
- c1订阅
source,share()引用计数变为1,上游interval启动 - 第二个订阅触发,外层
source被订阅,share()引用计数变为2
- c1订阅
- t=1~t=5秒
上游interval每秒发射一个值,依次输出c1 0、c1 1、c1 2、c1 3、c1 4
同时外层source收到的每个值都会进入delay(2000),延迟2秒后才会传递到switchMapTo
其中t=3秒时,最早延迟的第一个值流到switchMapTo,触发内部订阅source,所以后续的3、4会同时输出给c1和c2,对应你看到的c2 3、c2 4 - t=5秒时刻
take(5)已经发射完5个值,向上游发射完成通知,所有订阅source的订阅者(c1、外层source订阅、switchMap内部订阅)全部自动结束,share()引用计数归0,内部状态重置 - t=7秒时刻
外层source在t=5秒收到的最后一个值4,经过2秒延迟后流到switchMapTo,触发对source的新订阅。此时share()状态已经重置,因此会重新订阅上游的interval,interval重新从0开始发射值,就输出了你看到的后续c2 0到c2 4的重订阅结果
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

