首页 > 解决方案 > 合并运算符仅发出列表中第一个可观察对象的结果

问题描述

我正在尝试使用合并运算符来组合四个不同的 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)
            )
        }));
  };

标签: javascriptrxjs

解决方案


如果你想要一个发出 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;
             })
        )
    }));

};


推荐阅读