从多个Observable创建单个对象

时间:2017-11-29 21:46:54

标签: angular rxjs

假设我有以下功能:

getUsers() {
  return Observable.of(['Adam', 'Eve'])
}

getUserPets(user) {
  return Observable.of(user === 'Adam' ? 'Adam pets' : 'Eve pets');
}

getUserKids(user) {
  return Observable.of(user === 'Adam' ? 'Adam kids' : 'Eve kids');
}

我想创建函数获取用户,他们的宠物,孩子并将所有数据作为单个对象返回。类似的东西:

getUsersData() {
  // should return
  // [
  //    { user: 'Adam', pets: 'Adam pets', kids: 'Adam kids' },
  //    { user: 'Eve', pets: 'Eve pets', kids: 'Eve kids' }
  // ]
}

我尝试使用combineLatest运算符,但我的解决方案非常混乱。实现此类功能的最简单(或最可读)方式是什么?

沙箱:https://stackblitz.com/edit/angular-rspmy9?embed=1&file=app/app.component.ts

2 个答案:

答案 0 :(得分:1)

您可以使用forkJoinconcatMap

import { Component } from '@angular/core';
import { concatMap, concatAll, map, toArray } from 'rxjs/operators';
import { of } from 'rxjs/observable/of';
import { forkJoin } from 'rxjs/observable/forkJoin';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  constructor() {}

  getUsers() {
    return of(['Adam', 'Eve'])
  }

  getUserPets(user) {
    return of(user === 'Adam' ? 'Adam pets' : 'Eve pets');
  }

  getUserKids(user) {
    return of(user === 'Adam' ? 'Adam kids' : 'Eve kids');
  }

  getUsersData() {
    return this.getUsers().pipe(
      concatAll(), // unpack the array of users
      concatMap(user => forkJoin(this.getUserPets(user), this.getUserKids(user)).pipe(
        map(([pets, kids]) => ({ user, pets, kids }))
      )),
      toArray(),
    );
  }
}

然后,如果你想在模板中显示它,你将使用:

{{ getUsersData() | async | json }}

答案 1 :(得分:1)

使用combineLatest对我来说是可读的,但我不确定您的实现是什么样的。

function getUsers() {
  return Rx.Observable.of(['Adam', 'Eve'])
}

function getUserPets(user) {
  return Rx.Observable.of(user === 'Adam' ? 'Adam pets' : 'Eve pets');
}

function getUserKids(user) {
  return Rx.Observable.of(user === 'Adam' ? 'Adam kids' : 'Eve kids');
}

const users = getUsers().concatAll()
  .concatMap(user => Rx.Observable
    .combineLatest(getUserPets(user), getUserKids(user))
    .map(([pets, kids]) => ({user, pets, kids}))
  ).toArray();

users.subscribe(s => console.log(s));

jsbin example