rxjs将来自2个不同可观察对象的2个对象组合在一起

时间:2018-07-02 16:15:41

标签: javascript rxjs

我有2个可观察对象,分别在监听数据库调用。我需要将2个数组合并在一起。如果我有以下数组

let headers = new HttpHeaders().set('Authorization', 'Bearer ' + this.accessToken);

const endpoint1 = 'https://api.spotify.com/v1/me/player/currently-playing';
this.httpClient.get(endpoint1, { headers: headers }).subscribe((data: Object) => {
  console.log(data);
});

const endpoint2 = 'https://api.spotify.com/v1/me/player/play';
this.httpClient.put(endpoint2, { headers: headers }).subscribe((data: Object) => {
  console.log(data);
});

我想将它们合并在一起,以便得到一个像这样的可观察数组:

array1 = [{id: 1, content1: "string"}, {id: 2, content2: "string"}, {id: 3, content3: "string"}]
array2 = [{id: 1, contentX: "string"}, {id: 2, contentY: "string"}, {id: 3, contentZ: "string"}]

我有一些代码,但是我对如何继续感到很困惑,我似乎找不到合适的运算符或正确地将它们链接起来,有人对如何进行有很好的解释吗?到目前为止,这就是我所拥有的,但实际上不知道如何继续。

[{id:1, content1:"string", contentX:"string"}, {id:2, content2:"string", contentY:"string"}, {id:3, content3:"string", contentZ:"string"}]

感谢您的时间

2 个答案:

答案 0 :(得分:1)

我在这里进行了一个疯狂的猜测,并假设两个源可观察对象都在一个大块中发出它们的值。在这种情况下,您只想将两种排放都map合并为自定义(否则请发表评论)。例如:

const { of, combineLatest } = rxjs;
const { map } = rxjs.operators;

// simple merge-by-id
const mergeById = ([t, s]) => t.map(p => Object.assign({}, p, s.find(q => p.id === q.id)));

const db1$ = of([
  {id: 1, content1: 'string'},
  {id: 2, content2: 'string'},
  {id: 3, content3: 'string'},
]);

const db2$ = of([
  {id: 1, contentX: 'string'},
  {id: 2, contentY: 'string'},
  {id: 3, contentZ: 'string'},
]);

const all$ = combineLatest(db1$, db2$).pipe(
  map(mergeById)
);

all$.subscribe(console.log);
<script src="https://unpkg.com/rxjs@6.2.1/bundles/rxjs.umd.min.js"></script>

答案 1 :(得分:0)

我测试了3种方法:

const entityList1 = [{id: 1, name: 'Bob'}, {id: 2, name: 'John'}, {id: 3, name: 'Mike'}];
const entityList2 = [{id: 3, age: 22}, {id: 1, age: 25}, {id: 2, age: 20}];

@Yoshi的相同版本:

// V0
console.time('V0')
const mergeListsById_v0 = combineLatest(of(entityList1), of(entityList2)).pipe(
  map(([t, s]) => t.map(p => Object.assign({}, p, s.find(q => p.id === q.id))))
).subscribe(x => {
  console.log('result V0:', x);
  console.timeEnd('V0')
});

使用rxjs reduce运算符的版本:

// V1
console.time('V1')
const mergeListsById_v1 = merge(from(entityList1), from(entityList2)).pipe(
  reduce((entitiesById, entity) => {
    return {
      ...entitiesById,
      [entity.id]: {
        ...entitiesById[entity.id] || {},
        ...entity
      }
    };
  }, {}),
  map(entitiesById => Object.values(entitiesById)),
).subscribe(x => {
  console.log('result V1:', x);
  console.timeEnd('V1')
});

使用rxjs groupBy运算符的版本:

// V2
console.time('V2')
const mergeListsById_v2 = merge(from(entityList1), from(entityList2)).pipe(
  groupBy(entity => entity.id),
  mergeMap(groupedEntities$ => groupedEntities$.pipe(
    reduce((merged, entity) => ({...merged, ...entity}), {}))
  ),
  toArray()
).subscribe(x => {
  console.log('result V2:', x);
  console.timeEnd('V2')
});

您可以在这里使用以下版本:https://stackblitz.com/edit/rxjs-6aqjf9?devtoolsheight=60

如您所见,就性能而言,V2的性能要比其他产品好得多。