javascript - 合并运算符仅发出列表中第一个可观察对象的结果
问题描述
我正在尝试使用合并运算符来组合四个不同的 observables,它们都发出相同的 type T
。我想合并四个可观察对象,以便我有一个发出的可观察对象,T[]
然后我可以映射结果列表。
但是我注意到,当订阅合并的 observable 时,只会发出列表中第一个 observable 的结果。为什么是这样?
我认为这可能与正在使用的地图有关,但如果合并的 observable 的结果作为单个流发出,这应该不是问题,对吧?
this._signalRService.categoryGroupChangeSignal.pipe(
takeUntil(this.destroyObservables),
switchMap(changedCategoryGroupId => {
return this.getAllCategoryGroups$().pipe(
map(groups => [changedCategoryGroupId, groups])
);
}
)).subscribe(([changedCategoryGroupId, groups]: [string, CategoryGroup[]]) => {
//do stuff with merged groups list
});
getAllCategoryGroups$ = (): Observable<CategoryGroup[]> => {
return this.tenantListService.tenantList.pipe(switchMap( (tenantList: Tenant[]) => {
return merge(
this._categoryGroupService.getCustomTenantCategoryGroups(tenantList[0].id),
this._categoryGroupService.getCustomTenantCategoryGroups(tenantList[1].id),
this._categoryGroupService.getCustomTenantCategoryGroups(tenantList[2].id)
)
}));
};
解决方案
如果你想要一个发出 T[] 的 observable,我建议使用combineLatest。CombineLatest 将等到所有内容都发出一个值,然后发出一个包含所有值的数组,每次发出一个新值时,都会发出所有这些值的最新值。而 merge 一次发出一个,只有发出的 observable 才会给你一个值。
重要的是要注意combineLatest不会发出任何值,直到您提供它的每个可观察的,在您的情况下,3 个不同的,至少发出 1 个值。
combineLatest 的语法是相同的,因此您只需将 combineLatest 添加到您的 rxjs 导入并在 getAllCategoryGroups$ 中将 merge 更改为 combineLatest。
getAllCategoryGroups$ = (): Observable<CategoryGroup[]> => {
return this.tenantListService.tenantList.pipe(switchMap( (tenantList: Tenant[]) => {
return combineLatest(
this._categoryGroupService.getCustomTenantCategoryGroups(tenantList[0].id),
this._categoryGroupService.getCustomTenantCategoryGroups(tenantList[1].id),
this._categoryGroupService.getCustomTenantCategoryGroups(tenantList[2].id)
)
}));
};
然后,当您订阅它时,您将收到一个长度与您的 combineLatest 中的 observables 数量相同的数组
要展平数组数组,您可以使用map运算符,它允许您更改传递到 observable 链的输出。进入地图后,您可以通过多种方式展平数组,但我通常只是执行以下操作:
getAllCategoryGroups$ = (): Observable<CategoryGroup[]> => {
return this.tenantListService.tenantList.pipe(switchMap( (tenantList: Tenant[]) => {
return combineLatest(
this._categoryGroupService.getCustomTenantCategoryGroups(tenantList[0].id),
this._categoryGroupService.getCustomTenantCategoryGroups(tenantList[1].id),
this._categoryGroupService.getCustomTenantCategoryGroups(tenantList[2].id)
).pipe(
map(lists => {
const arrayToReturn = [];
for (const list of lists) {
arrayToReturn.push(...list);
}
return arrayToReturn;
})
)
}));
};
推荐阅读
- android - Kotlin 选择了未在 Dialog Fragment 中显示的图像
- react-native - 如何更改树莓派蓝牙名称
- python - 提取价格 - 美丽的汤
- javascript - 调用后端后,动作函数总是在 React 中返回相同的减速器类型
- kubernetes - Kubernetes rbac pod/exec create 操作被禁止
- javascript - 如何在普通的前端 javascript 文件中使用 node.js 函数
- r - 使用 R 中的下拉菜单选项在 URL 未更改时抓取表格
- c++ - 有没有办法通过指定它们各自的范围来比较 2 个向量?
- vue.js - 如何将 codepen.io 页面转换为 Vue 应用程序
- reactjs - 根据用户是否有权访问来保护路由