当另一个流发出时如何动态更改流间隔

时间:2018-09-05 15:10:05

标签: rxjs

所以我有一个由字符串数组组成的流。

const msgs = ['Searching...', 'Gathering the Data...', 'Loading the Dashboard...'];
const msgs$ = Observable.from(msgs);

我需要每3秒依次发出这些消息之一,直到dataFetched$流发出为止-这基本上意味着所有数据都已到达页面。我无法穿越它们。一旦看到最后一条消息,但数据尚未到达,就不应更改。

随着时间的推移,我可以使用msgs函数遍历RxJS zip中的每个字符串

const longInt$: Observable<number> = Observable.interval(3000);
const longMsgsOverTime$ = Observable.zip(msgs$, longInt$, msg => msg);

然后在dataFetched$流发出时,我需要切换到{p}

shortInt$

并继续显示加载消息,直到最后一条可见。每个消息只能看到一次。

我非常介意-我可以满足一些要求,但不能使其完全正常运行。 经过多次尝试,我得出结论,我们需要将 const longInt$: Observable<number> = Observable.interval(1500); 数组包装在一个Subject中,以防止在从msgs切换到longInt$之后再次遍历所有循环。

===================编辑===================== 以下是ggradnig的答案和代码,我炮制了这种难看(出于调试目的):

shortInt$

下面是我的chrome控制台的屏幕截图,以查看发生了什么。 setLoaderMsg(){ console.log('%c setting loader msg', 'border: 10px dotted red;'); const msgs$ = Observable.from(['Searching...', 'Gathering the Data...', 'Loading the Dashboard...', 'Something something...', 'yet another msg...', 'stop showing me...']), shortInt$ = Observable.interval(250).pipe( tap(v => console.log('%c short v', 'background: green;',v)) ), longInt$ = Observable.interval(3000).pipe( tap(v => console.log('%c long v', 'background: red;',v)), takeUntil(this.dataFetched$) ), // interval$ = Observable.interval(3000).pipe(takeUntil(this.dataFetched$)).pipe(concat(Observable.interval(250))), interval$ = longInt$.pipe(concat(shortInt$)); Observable.zip(msgs$, interval$, msg => msg) // Observable.zip(msgs$, interval$) .pipe(tap(v => { console.log('%c v', 'background: black; border: 1px solid red; color: white;', v); this.loaderMsg = v; })) .subscribe( () => {}, //next () => {}, //error // () => this.loading = false //complete () => { console.log('%c complete', 'background: yellow; border: 2px solid red'); // this.loading = false; } ); } 流将记录绿色消息,即使您发出shortInt$流(橙色虚线边框),您也不会看到绿色消息。 在“获取数据发射”日志的下方,我们应该看到绿色的背景消息,表示shortInt $流正在发射值。

enter image description here

=================================第二次编辑============= ===========

以下是dataFetched$可以观察到的:

dataFetched$

1 个答案:

答案 0 :(得分:1)

听起来像takeUntilconcat的任务。

第一个可观察的是longInt$dataFetched$发出后便立即完成。对于此要求,可以使用takeUntil。它以另一个可观察对象作为参数,一旦该可观察对象发出,则可观察源将完成。

从文档中

  

发出源Observable发出的值,直到notifier Observable发出值为止。

因此,第一步将是:

const longInt$: Observable<number> = Observable.interval(3000)
    .pipe(takeUntil(dataFetched$));

接下来,您想concat观察其他shortInt$。 Concat将让第一个可观察对象完成,然后让第二个可观察对象接管。

从文档中

  

创建一个输出Observable,该输出依次从给定的Observable发出所有值,然后移至下一个。

这看起来像这样:

const longMsgsOverTime$ = Observable.zip(msgs$, 
    longInt$.pipe(concat(shortInt$)), msg => msg);

注意:如果您使用的是RxJS 5或更低版本,请用相应的运算符替换pipe(..)语句。例如,.pipe(concat(...))变成.concat(...)

以下是StackBlitz上的一个示例:https://stackblitz.com/edit/angular-mtyfxd