You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用next后订阅延迟Observable出现意外输出的RxJS问题

RxJS中shareReplay与时序问题的分析与解决

问题复现

以下是触发问题的代码:

let isNull = true;
const a$ = new Subject<void>();
const b$ = a$.pipe(
  switchMap(() => {
    if (!isNull)
      return of(true).pipe(
        tap(() => console.log('should be shared')),
        delay(100) // (3)
      );
    else return of(null);
  }),
  shareReplay(1)
);

b$.subscribe((b) => console.log('1', b));
a$.next(); // (1)
b$.subscribe((b) => console.log('2', b));
isNull = false;
a$.next(); // (2)
b$.subscribe((b) => console.log('3', b));

实际输出:

1 null
2 null
should be shared
3 null // 不符合预期的行
1 true
2 true
3 true

预期输出:

1 null
2 null
should be shared
1 true
2 true
3 true

原因分析

时序与缓存机制冲突

  1. 执行a$.next()(标记1)时,switchMap返回同步的of(null),shareReplay(1)缓存null,第一个订阅者收到1 null;第二次订阅时直接读取缓存,输出2 null。
  2. 修改isNull后执行a$.next()(标记2),switchMap切换到异步的of(true).pipe(delay(100)),但此时该Observable尚未推送任何值,shareReplay(1)的缓存仍为null。
  3. 第三次订阅时,shareReplay会先返回缓存的null,导致输出3 null;100ms后delay完成,true被推送,所有订阅者收到对应true值。

移除delay后问题消失的原因

无delay时,of(true)同步推送值,a$.next()(标记2)执行后shareReplay缓存立即更新为true,第三次订阅直接读取新缓存,不会输出旧的null。

优雅解决方案

要同时保留2 null的输出并避免3 null,需让新订阅者仅接收当前活跃Observable的值,结合switchMap与switchLatest实现:

let isNull = true;
const a$ = new Subject<void>();

const b$ = a$.pipe(
  switchMap(() => {
    const source = !isNull 
      ? of(true).pipe(tap(() => console.log('should be shared')), delay(100))
      : of(null);
    // 为每个切换后的源单独配置shareReplay,确保缓存独立
    return source.pipe(shareReplay(1));
  }),
  // 始终订阅最新的Observable,新订阅者不会读取旧源的缓存
  switchLatest()
);

b$.subscribe((b) => console.log('1', b));
a$.next();
b$.subscribe((b) => console.log('2', b));
isNull = false;
a$.next();
b$.subscribe((b) => console.log('3', b));

输出结果:

1 null
2 null
should be shared
1 true
2 true
3 true

方案解析

  • 每个switchMap返回的Observable单独使用shareReplay(1),确保缓存仅属于当前活跃的数据源,避免跨源缓存污染。
  • switchLatest操作符会自动切换到最新的Observable,新订阅者只会等待当前活跃源的推送,不会读取旧源的缓存值,完美匹配预期输出。

内容的提问来源于stack exchange,提问作者Szymon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 12:55:19