我有多个可观察对象,它们在页面的生命周期内发出值。例如:
chartData$: Observable;
tableData$: Observable;
filterData$: Observable;
用户可以随时单击“下载”按钮,并获取结合了以下每个可观察对象最后发出的值的JSON:
downloadButtonClicked$.pipe(
combine chartData$, tableData$ and filterData$ // <- how do I get latest values here?
).subscribe(([chart, table, filter]) => downloadJson(chart, table, filter))
但是,当这3个可观察变量中的任何一个在页面生命周期中发出值时,仅在单击“下载”时,才不应调用downloadJson
函数。
TLDR;
使用最优雅的解决方案(由Mike建议) https://stackblitz.com/edit/typescript-jm3zma?file=index.ts
答案 0 :(得分:4)
您可以这样做:
combineLatest([chartData$, tableData$, filterData$]).pipe(
switchMap(result => downloadButtonClicked$.pipe(map(() => result)))
).subscribe(([chart, table, filter]) => {
downloadJson(chart, table, filter);
});
每当chartData$
,tableData$
或filterData$
发出新值时,它将为downloadButtonClicked$
创建一个新的内部订阅,将新数据传递下来。
注意:只有所有chartData$
,tableData$
和filterData$
都发出了第一个值后,才能创建订阅。如果您仍然需要在这种情况下触发下载,则可以使用defaultIfEmpty
。
答案 1 :(得分:3)
如果您想在每个可观察源完成之前从它们中获取最后一个值,则可以使用forkJoin()
,它们在所有它们都完成之后只会发出一次。
如果要从可观察的每个源排放每个排放,则可以使用combineLatest
。
编辑:
您可以将每个可观察的来源与shareReplay(1)
链接起来,这样,当您订阅它们时,您将获得最新的价值。
const chartDataShared$ = chartData$.pipe(shareReplay(1));
tableDataShared$ = ...;
filterDataShared$ = ...;
combineLatest([chartDataShared$, tableDataShared, filterDataShared$]).pipe(
take(1)
);
通过这种方式,您将获得每个参数发出的最新值。但是,这意味着在代码的其他部分,您将需要使用例如。 chartDataShared$
而不是chartData$
。
答案 2 :(得分:1)
combineLastest将在所有可观察对象都发出后发出。您可以使用switchMap从downloadButtonClicked $切换。
downloadButtonClicked$.pipe(
switchMap(
() => combineLatest([chartData$, tableData$, filterData$])
)
).subscribe(([chart, table, filter]) => downloadJson(chart, table, filter));
答案 3 :(得分:1)
您可以简单地使用withLatestFrom
。
downloadButtonClicked$.pipe(
withLatestFrom(chartData$, tableData$, filterData$)
).subscribe(([_, chart, table, filter]) => downloadJson(chart, table, filter))
可观察对象仅在downloadButtonClicked$
发出并将其值与chartData$
,tableData$
和filterData$
的最新值组合时才发出。