【问题标题】:Angular 6 pipe RxJs operator to chain 3 dependant observablesAngular 6 管道 RxJs 运算符链接 3 个相关的可观察对象
【发布时间】:2018-07-06 12:35:57
【问题描述】:

我有 3 个相关的 Rest API 资源(比如说 observables),如下所示:

第一个 observable 产生一个用户数组,像这样:

getUsers(): Observable<User[]>
    [
      {
        "id": 1,
        "name": "Peter",
        "surname": "Smith"
      },
      {
        "id": 2,
        "name": "John",
        "surname": "Wayne"
      },
      ...
    ]

第二个 observable 可用于获取分配给用户的地址,因此输入参数是用户 ID,并返回一个作为地址数组的项目:

getUserAddresses(user_id: string): Observable<Address[]>
    [
      {
        "id": 1,
        "city": "London",
        "street": "Wicombe 34"
      },
      {
        "id": 2,
        "city": "Paris",
        "street": "La fever 20"
      },
      ...
    ]

第三个 observable 可用于获取分配给用户的公司,因此输入参数是用户 ID,并返回一个项目作为公司数组:

getUserCompanies(user_id: string): Observable<Company[]>
    [
      {
        "id": 1,
        "name": "Fintch CO",
        "state": "France"
      },
      {
        "id": 2,
        "name": "C&C inc.",
        "state": "USA"
      },
      ...
    ]

我想将这 3 个 observable 链接成一个,它将再次将结果作为一个项目产生,其中将包含用户数组以及他们的附加地址数组和公司数组,如下所示:

    [
      {
        "id": 1,
        "name": "Peter",
        "surname": "Smith",
        "addreesses": 
               [
                 {
                   "id": "1",
                   "city": "London",
                   "street": "Wicombe 34"
                 },
                 {
                   "id": "2",
                   "city": "",
                   "street": "La fever 20"
                 }
               ],
        "companies": 
               [
                 {
                   "id": "1",
                   "name": "Fintch CO",
                   "state": "France"
                 },
                 {
                   "id": "2",
                   "name": "C&C inc.",
                   "state": "USA"
                 }
               ]
        }
      },
      {
        "id": 2,
        "name": "John",
        "surname": "Wayne",
        "addresses": [...],
        "companies": [...],
      },
      ...
    ]

在使用 RxJs 6 的 Angular 6 中,操作符组合应该如何实现? 非常感谢您的建议。

【问题讨论】:

    标签: angular rxjs observable operator-keyword


    【解决方案1】:

    这样的东西可以工作

    getUsers()
    .pipe(
      switchMap(users => from(users)),
      mergeMap(user => forkJoin(getAddresses(user.id), getCompanies(user.id))
                       .pipe(map(data => ({user, addresses: data[0], companies: data[1] })))
      tap(data => data.user.addresses = data.addresses),
      tap(data => data.user.companies = data.companies),
      map(data => data.user),
      toArray()
      )
    )
    

    应用于不同的用例,类似的链将在here进行更详细的解释。

    【讨论】:

    • 如果源第一个可观察对象将用户数组作为其他一些简单对象的内部属性生成,那么操作符链的外观将如何:{ "group_name": "employees", "group_id" :“1”,“用户”:[...] }
    • 如果 ai 正确理解您的观点,您应该将“switchMap(data => from(data.users))”作为链中的第一个运算符
    • 是的,如果我期待相同的结果(仅 users 数组),这将起作用,但是如果我希望最终结果包含来自第一个可观察对象(group_name,group_id)的所有信息?
    • 如果我不需要公司数组怎么办。只有我需要的地址? @Picci
    【解决方案2】:

    要链接 observable,您可以使用 flatMap 函数。这个函数就像 Promise 那样,意味着这个函数只有在 observable 解析为一个值时才会执行。

    还有一个名为 forkJoin 的可观察函数,它允许您等待多个异步请求全部解析为一个值。

    例子:

    getUsers().flatMap((users) => {
        // the users variable is the list of users
        var multipleObservables = [];
        users.forEach((u) => {
          multipleObservables.push(
             getUserAddresses(u.id).map((usersAddresses) => {
                u.addresses = usersAddresses;
                return u;
             });
          );
        });
        return forkJoin(multipleObservables);
    }).flatMap((usersWithAddresses) => {
        // the usersWithAddresses variable is an array of users which also have their addresses
        var multipleObservables = [];
        usersWithAddresses.forEach((u) => {
           multipleObservables.push(
              getUserCompanies(u.id).map((usersCompanies) => {
                 u.companies = usersCompanies;
                 return u;
              });
           );
        });
        return forkJoin(multipleObservables);
    });
    

    您可以编写类似这样的内容来链接您的请求并增加您的用户对象。

    【讨论】:

    • 这种方法对我不起作用,u.id 未定义
    • getUsers() 返回的对象是用户数组吗? users 变量中究竟包含什么?
    • getUsers() 返回的确切数据结构显示在我的示例中
    • 我不确定为什么会发生这种情况,用户对象应该是用户对象的数组。我想作为一个测试,你可以在var multipleObservables = []; 行之前做console.log(users[0].id),看看你是否得到一个id。
    【解决方案3】:

    这里是组合操作符,它们在数组中发出结果 (reference):

    我建议将它们全部阅读一遍,以找出您喜欢的内容并找到最适合您的场景。

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 2018-10-25
      • 1970-01-01
      • 1970-01-01
      • 2018-12-02
      • 2019-10-31
      • 2020-09-05
      • 1970-01-01
      • 2019-08-06
      • 2021-08-26
      相关资源
      最近更新 更多