繁体   English   中英

RxJS - 一个 observable 'A' 不会停止发射从同一个 observable 'A' 传送的 takeUntil

[英]RxJS - An observable 'A' doesn't stop emitting with a takeUntil that is piped from the same observable 'A'

我有一个可观察的,在单击开始按钮后每秒向控制台打印一个数字。 单击开始按钮 5 秒后,可观察对象应停止打印。

单击开始按钮后每秒开始条件

点击开始按钮五秒后结束条件

不起作用的代码

const startClick$ = fromEvent(document.getElementById('start'), 'click');
const stop$ = startClick$.pipe(switchMapTo(interval(5000)));
const printInterval$ = interval(1000).pipe(takeUntil(stop$));
const startPrint$ = startClick$.pipe(switchMapTo(printInterval$));

startPrint$.subscribe(
  value => {
    console.log('new value is:', value);
  },
  () => {
    console.log('there was some error!');
  },
  () => {
    console.log('i have completed');
  }
);

stop$.subscribe(() => {
  console.log('i should stop right now!!');
});

单击开始按钮后五秒钟后,startPrint$ Observable 不会停止发射。

有效的代码

const endClick$ = fromEvent(document.getElementById('end'), 'click');
const stopWithEndClick$ = endClick$.pipe(switchMapTo(interval(5000)));
const printInterval1$ = interval(1000).pipe(takeUntil(stopWithEndClick$));
const startPrint1$ = startClick$.pipe(switchMapTo(printInterval1$));

startPrint1$.subscribe(
  value => {
    console.log('1: new value is:', value);
  },
  () => {
    console.log('1: there was some error!');
  },
  () => {
    console.log('1: i have completed');
  }
);

stopWithEndClick$.subscribe(() => {
  console.log('1: i should stop right now!!');
});

在这里,我有另一个按钮end ,我在单击 end 按钮后 5 秒内执行。 在这种情况下,observable 会按预期停止发射。

我怎样才能使第一个案例工作,我在这里犯了任何错误吗? 整个工作代码可以在https://stackblitz.com/edit/take-until-issue?file=index.ts 找到

发生这种情况是因为 RxJS 运算符中的订阅顺序。 当您第一次单击“开始”按钮时,第一个收到通知的是stop$ ,但没有人在收听stop$ ,因此通知不会触发任何内容。 你看到"'i should stop right now!!' 只是因为你最后自己订阅了。

因此,最简单的解决方案是将stop$链创建为一个 Observable,它只会在您订阅后开始发射,例如timer(5000) ,它只发射一次然后完成。

const stop$ = timer(5000);

您更新的演示: https://stackblitz.com/edit/take-until-issue-or4okm?file=index.ts

请注意,您可能会得到不同数量的结果,因为 RxJS (通常是 JavaScript)不能保证5000ms正好是5000ms 这同样适用于1000ms ,因此有时事件可能会以不同的顺序触发。 如果您只想要 5 个结果,则更好地使用例如take(5) 此外,对于日志记录,最好使用例如tap(v => console.log(v))这样您就不会再次订阅。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM