所以我有一个由字符串数组组成的流。
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 $流正在发射值。
=================================第二次编辑============= ===========
以下是dataFetched$
可以观察到的:
dataFetched$
答案 0 :(得分:1)
听起来像takeUntil
和concat
的任务。
第一个可观察的是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