Rxjs 当我在第二次订阅中添加延迟操作符时,共享一个可观察对象将变成单播

Rxjs 当我在第二次订阅中添加延迟操作符时,共享一个可观察对象将变成单播,rxjs,rxjs-observables,Rxjs,Rxjs Observables,以下代码按预期工作: const source = interval(1000).pipe( take(5), share() ); source.subscribe(x => console.log('c1', x)); setTimeout(() => { source.subscribe(x => console.log('c2', x)); }, 2000); 产生以下输出: C10 c1 1

以下代码按预期工作:

    const source = interval(1000).pipe(
        take(5),    
        share()
  );

  source.subscribe(x => console.log('c1', x));
  setTimeout(() => {
    source.subscribe(x => console.log('c2', x));
  }, 2000);
产生以下输出: C10 c1 1 c1 2 c2 2 c1 3 c2 3 c1 4 c2 4

但是当我将第二个订阅更改为使用delay(2000)而不是setTimeout()时 我得到一个不共享的不同流

    const source = interval(1000).pipe(
        take(5),    
        share()
  );

  source.subscribe(x => console.log('c1', x));

  source.pipe(delay(2000)).subscribe(x => console.log('c2', x));
生成此输出:

C10 c1 1 c1 2 c2 0 c1 3 c2 1 c1 4 c2 2 c2 3 c2 4

如何让第二个订户使用共享流? 我显然不完全理解RX操作员是如何在引擎盖下工作的。

使用
source.pipe(delay(2000))
与使用
setTimeout()
完全不同
delay()
操作符将延迟源的每次发射,这意味着您仍将立即进行两次订阅

您可能想做的是:

of(null)
  .pipe(
    delay(2000),
    switchMapTo(source),
  )
  .subscribe();
或者这应该做同样的事情:

concat(timer(2000), source)
  .subscribe();
使用
source.pipe(delay(2000))
与使用
setTimeout()
完全不同
delay()
操作符将延迟源的每次发射,这意味着您仍将立即进行两次订阅

您可能想做的是:

of(null)
  .pipe(
    delay(2000),
    switchMapTo(source),
  )
  .subscribe();
或者这应该做同样的事情:

concat(timer(2000), source)
  .subscribe();
视觉 这是c2在两秒钟后订阅的原始流

src:0-1-2-3-4
c1:0-1-2-3-4
c2:----2-3-4
你的流中c2立即订阅,并将每次发射延迟2秒

src:0-1-2-3-4
c1:0-1-2-3-4
c2:----0-1-2-3-4
共享源 共享一个源与拥有相同的输出是不同的

考虑这一点:

const src=间隔(1000)。管道(
以(5)为例,
映射(x=>x+5),
股份()
);
src.pipe(map(x=>x-1)).subscribe(console.log);//c1
src.pipe(map(x=>x+1)).subscribe(console.log);//c2
输出:

src:5-6-7-8-9
c1:4-5-6-7-8
c2:6-7-8-9-10
尽管它们都有不同的输出
c1
c2
都有相同的来源
c1
c2
不生成任何数字,它们只是从给定的数字中加1减1。他们改变了他们的来源

这与您在第二个示例中所做的相同。当发射发生时,延迟会发生变化,而不是转换数字
c2
发射与源相同的流,它在2秒后才开始发射,在源完成后2秒仍在发射

设置超时延迟
const source=间隔(1000)。管道(
以(5)为例,
股份()
);
订阅(x=>console.log('c1',x));
source.subscribe(x=>
setTimeout(U8;=>
控制台日志('c2',x),
2000
)
);
在订阅之前等待
const source=间隔(1000)。管道(
以(5)为例,
股份()
);
订阅(x=>console.log('c1',x));
计时器(2000)。管道(
开关映射(=>source)
).subscribe(x=>console.log('c2',x));
A视觉 这是c2在两秒钟后订阅的原始流

src:0-1-2-3-4
c1:0-1-2-3-4
c2:----2-3-4
你的流中c2立即订阅,并将每次发射延迟2秒

src:0-1-2-3-4
c1:0-1-2-3-4
c2:----0-1-2-3-4
共享源 共享一个源与拥有相同的输出是不同的

考虑这一点:

const src=间隔(1000)。管道(
以(5)为例,
映射(x=>x+5),
股份()
);
src.pipe(map(x=>x-1)).subscribe(console.log);//c1
src.pipe(map(x=>x+1)).subscribe(console.log);//c2
输出:

src:5-6-7-8-9
c1:4-5-6-7-8
c2:6-7-8-9-10
尽管它们都有不同的输出
c1
c2
都有相同的来源
c1
c2
不生成任何数字,它们只是从给定的数字中加1减1。他们改变了他们的来源

这与您在第二个示例中所做的相同。当发射发生时,延迟会发生变化,而不是转换数字
c2
发射与源相同的流,它在2秒后才开始发射,在源完成后2秒仍在发射

设置超时延迟
const source=间隔(1000)。管道(
以(5)为例,
股份()
);
订阅(x=>console.log('c1',x));
source.subscribe(x=>
setTimeout(U8;=>
控制台日志('c2',x),
2000
)
);
在订阅之前等待
const source=间隔(1000)。管道(
以(5)为例,
股份()
);
订阅(x=>console.log('c1',x));
计时器(2000)。管道(
开关映射(=>source)
).subscribe(x=>console.log('c2',x));

这些答案真的帮助我对RXJS有了更深的理解,少魔法多逻辑:-)很多感谢这些答案真的帮助我对RXJS有了更深的理解,少魔法多逻辑:-)很多感谢