You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从已有Observable创建新Observable?RxJS代码实现疑问

How to Extract Combined Roles from User Observable

Hey there! Let's fix up that usedRoles observable you're working on. The key here is mixing RxJS operators with array methods correctly—let's break it down step by step.

The Core Problem

Your users observable emits an array of User objects, each with their own roles: Role[] array. You want to take all those role arrays, flatten them into a single list of roles, and wrap that in an Observable<Role[]>.

The Correct Implementation

Here's how to write it properly:

import { map } from 'rxjs/operators';

public get usedRoles(): Observable<Role[]> {
  return this.users.pipe(
    // Take the emitted User[] and flatten all their roles into a single Role[]
    map(users => users.flatMap(user => user.roles))
  );
}

If you're using an older RxJS version that uses chained operators instead of pipe(), it looks like this:

public get usedRoles(): Observable<Role[]> {
  return this.users.map(users => users.flatMap(user => user.roles));
}

Why Your Initial Approach Was Off

You tried using RxJS's flatMap (now called mergeMap), but that's for flattening streams of observables/promises/arrays into a single stream of values. If you'd continued with flatMap, you'd end up with an Observable<Role> (emitting individual role objects one by one) instead of an Observable<Role[]> (emitting a single array of all roles).

Instead, we use RxJS's map operator to transform the emitted User[] directly into a Role[], and use the array's flatMap method (not RxJS's) to flatten the nested Role[][] into a single Role[].

Bonus: Deduplicate Roles (If Needed)

If you want to avoid duplicate roles (since multiple users might share the same role), you can add deduplication logic. For example, if your Role has an id property:

public get usedRoles(): Observable<Role[]> {
  return this.users.pipe(
    map(users => {
      const seenRoleIds = new Set<number>();
      return users.flatMap(user => user.roles).filter(role => {
        if (!seenRoleIds.has(role.id)) {
          seenRoleIds.add(role.id);
          return true;
        }
        return false;
      });
    })
  );
}

Or if you just want to deduplicate based on object references (works if roles are singletons):

map(users => [...new Set(users.flatMap(user => user.roles))])

内容的提问来源于stack exchange,提问作者Anand

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:06:10