问题描述
我需要向同一端点发出 2 个 AJAX 请求,以返回过滤和未过滤的数据。然后我需要组合结果并在处理中使用它们。
loadUnfilteredData() {
// remember status
const {status} = this.service.filters;
delete this.service.filters.status;
this.service.saleCounts$()
.subscribe((appCounts) =>
this.processUnfilteredData(appCounts)
);
// restore status
if (status) {
this.service.filters.status = status;
}
}
loadFilteredData() {
this.service.saleCounts$()
.subscribe((appCounts) =>
this.processFilteredData(appCounts)
);
}
问题是 this.service.saleCounts$()
是不纯的,而不是使用参数只是使用 this.service.filters
。
这就是为什么我必须存储 status
,然后从过滤器中删除它,然后执行请求,然后恢复(因为其他请求使用相同的过滤器)。
所以我不能只对两个 observable 做 combineLatest
(因为我需要恢复)。
有什么解决办法吗?
(p.s. 我知道这种方法很恶心,我知道状态管理和纯函数。只是想知道有没有什么漂亮的解决方案)。
解决方法
我相信您的约束要求两个操作依次运行,一个接一个,而不是像我们使用 combineLatest
时通常的情况那样并行运行。
要顺序运行两个 Observable,我们可以使用 switchMap
(作为现代 rxjs 中 pipe
调用中的运算符):
doFirstOperation()
.pipe(
switchMap(result => return doSecondOperation())
);
一个潜在的问题是,当您将 doFirstOperation
的结果switchMap
访问 doSecondOperation
的结果时,您将无法访问 doFirstOperation()
.pipe(
switchMap(firstResult => return doSecondOperation())
.pipe(
map(secondResult => [firstResult,secondResult])
)
);
的结果。为了解决这个问题,我们可以这样做:
map
即,使用 switchMap
将 loadData() {
const { status } = this.service.filters;
delete this.service.filters.status;
return this.service
.saleCounts$()
.pipe(
finalize(() => {
if (status) {
this.service.filters.status = status;
}
}),switchMap(filteredData => {
return this.service
.saleCounts$() // unfiltered query
.pipe(map(unfilteredData => [filteredData,unfilteredData]));
})
)
.subscribe(results => {
const [filteredData,unfilteredData] = results;
this.processFilteredData(filteredData);
this.processUnfilteredData(unfilteredData);
});
}
的返回值更改为包含这两个值的数组。
将其与您对状态管理的“令人厌恶的”要求放在一起,您可以使用以下内容:
combineLatest
我并没有太多人会将其归类为漂亮,但它至少允许您以看起来像使用 @property
的方式获得结果,但可以解决您的不纯方法强加的限制.