Rxjs 如何在另一个流发出时动态更改流间隔
所以我有一个由字符串数组组成的流Rxjs 如何在另一个流发出时动态更改流间隔,rxjs,Rxjs,所以我有一个由字符串数组组成的流 const msgs = ['Searching...', 'Gathering the Data...', 'Loading the Dashboard...']; const msgs$ = Observable.from(msgs); 我需要每3秒钟按顺序发出其中一条消息,直到dataFetched$stream发出为止,这基本上意味着所有数据都到达页面。我不能在它们之间循环。一旦看到最后一条消息但数据尚未到达,它就不应该更改 我可以使用RxJS-zip
const msgs = ['Searching...', 'Gathering the Data...', 'Loading the Dashboard...'];
const msgs$ = Observable.from(msgs);
我需要每3秒钟按顺序发出其中一条消息,直到dataFetched$
stream发出为止,这基本上意味着所有数据都到达页面。我不能在它们之间循环。一旦看到最后一条消息但数据尚未到达,它就不应该更改
我可以使用RxJS-zip
函数查看msgs
中的每个字符串
const longInt$: Observable<number> = Observable.interval(3000);
const longMsgsOverTime$ = Observable.zip(msgs$, longInt$, msg => msg);
并继续显示加载消息,直到最后一条消息可见。每条消息只应显示一次
这对我来说是相当令人费解的——我可以勾选一些要求,但不能让它完全工作。
经过多次尝试,我得出结论,我们需要将msgs
数组包装在一个主题中,以防止在我们从longInt$
切换到shortInt$
后再次循环使用所有这些数组
============================编辑=====================
以下是ggradnig的答案和代码,我编造了这个丑陋的东西(为了调试):
下面是我的chrome控制台的截图,看看会发生什么。shortInt$
流将记录绿色消息,因为您可以看到它从未发生过,即使dataFetched$
流发出(橙色虚线边框)。
在“fetch data emit”日志下面,我们应该看到绿色的背景消息,表示shortInt$流正在发射值
第二次编辑========================
下面是可观察到的dataFetched$
:
fetchData(){
console.log('%c fetching now', 'border: 2px dashed purple');
// this.initLoader();
this.dataFetched$ = Observable.combineLatest([
this.heroTableService.getHeroTableData([SubAggs.allNetworks.key], AggFieldsMap.legends.name),
this.researchService.benchmark(this.getSubAggsForOverviewTbl()),
this.multiLineChartService.getEngagementOverTime(this.getSubAggsForNetworkEngagementsOverTimeTable())
]).pipe(
share(),
delay(7000),
tap(v => {
console.log('%c fetch data emit', 'border: 2px dashed orange', v);
})
);
const sub = this.dataFetched$.subscribe(([heroTableRes, benchmarkRes, netByEngRes]: [ITable[], IBenchmarkResponse, any]) => {
// this.loading = false; ==> moved to dashboard
//xavtodo: split this shit into .do() or .tap under each http request call
//hero table logic here
this.heroTableData = heroTableRes;
//////////////////////////////////////////////////////
//engagement-by-network-table
this.engagementByNetworkData = this.researchService.extractDataForEngagementByNetworkTable(benchmarkRes, this.getSubAggsForOverviewTbl());
//////////////////////////////////////////////////////
//network eng over time logic here MULTI LINE CHART
this.engagementMultiLineData = this.multiLineChartService.extractEngagementData(netByEngRes, this.getSubAggsForNetworkEngagementsOverTimeTable());
this.networks = this.multiLineChartService.getNetworks();
this.multilineChartEngagements = Util.getNetworksWithAltNames(this.networks);
this.publishedContentData = this.multiLineChartService.extractPublishedData(netByEngRes);
//combined multiline chart
this.multiLineChartData = {
publishedData: this.publishedContentData,
engagementData: this.engagementMultiLineData
};
});
this.addSubscription(sub);
}
听起来像是
takeUntil
和concat
的任务
第一个可见值是longInt$
。它在dataFetched$
发出后立即完成。对于此要求,您可以使用takeUntil
。它将另一个可观测值作为参数,一旦该可观测值发出,源可观测值将完成
从文档中:
发出源可观察对象发出的值,直到通知程序
可观察对象发出值为止
因此,第一步是:
const longInt$: Observable<number> = Observable.interval(3000)
.pipe(takeUntil(dataFetched$));
注意:如果您使用的是RxJS 5或更低版本,请使用相应的运算符替换管道(..)语句。例如,.pipe(concat(…)
变成.concat(…)
这里有一个关于StackBlitz的例子:我遵循了你的建议,但我从未输入shortInt$流。数据到达,但消息使用longInt$继续循环。我的代码在这里,这是由于您如何使用
zip
->在您的回答中,您使用longInt$压缩了3个值的可观测值(字符串数组),concent$与shortInt$合并,但可观测间隔永远不会发出complete
,因此,concat函数永远不会执行。嗯。。longInt$应该在takeUntil
通知发出时完成。我在我的帖子中添加了一个StackBlitz示例,您可以查看:)谢谢您的帮助。我仍然无法让它在我的应用程序中运行,即使是完全按照你的例子。当我进入它的流时,我只看到了longInt$
排放物。
fetchData(){
console.log('%c fetching now', 'border: 2px dashed purple');
// this.initLoader();
this.dataFetched$ = Observable.combineLatest([
this.heroTableService.getHeroTableData([SubAggs.allNetworks.key], AggFieldsMap.legends.name),
this.researchService.benchmark(this.getSubAggsForOverviewTbl()),
this.multiLineChartService.getEngagementOverTime(this.getSubAggsForNetworkEngagementsOverTimeTable())
]).pipe(
share(),
delay(7000),
tap(v => {
console.log('%c fetch data emit', 'border: 2px dashed orange', v);
})
);
const sub = this.dataFetched$.subscribe(([heroTableRes, benchmarkRes, netByEngRes]: [ITable[], IBenchmarkResponse, any]) => {
// this.loading = false; ==> moved to dashboard
//xavtodo: split this shit into .do() or .tap under each http request call
//hero table logic here
this.heroTableData = heroTableRes;
//////////////////////////////////////////////////////
//engagement-by-network-table
this.engagementByNetworkData = this.researchService.extractDataForEngagementByNetworkTable(benchmarkRes, this.getSubAggsForOverviewTbl());
//////////////////////////////////////////////////////
//network eng over time logic here MULTI LINE CHART
this.engagementMultiLineData = this.multiLineChartService.extractEngagementData(netByEngRes, this.getSubAggsForNetworkEngagementsOverTimeTable());
this.networks = this.multiLineChartService.getNetworks();
this.multilineChartEngagements = Util.getNetworksWithAltNames(this.networks);
this.publishedContentData = this.multiLineChartService.extractPublishedData(netByEngRes);
//combined multiline chart
this.multiLineChartData = {
publishedData: this.publishedContentData,
engagementData: this.engagementMultiLineData
};
});
this.addSubscription(sub);
}
const longInt$: Observable<number> = Observable.interval(3000)
.pipe(takeUntil(dataFetched$));
const longMsgsOverTime$ = Observable.zip(msgs$,
longInt$.pipe(concat(shortInt$)), msg => msg);