将RXJS可观察的结果合并为一个

时间:2018-09-04 13:45:24

标签: javascript angular typescript rxjs observable

我的数据库中有两个节点:

users: {user1: {uid: 'user1', name: "John"}, user2: {uid: 'user2', name: "Mario"}}
homework: {user1: {homeworkAnswer: "Sample answer"}}

某些用户可能有功课,也可能没有功课。

我想通过一次调用就获得所有用户的列表以及每个用户的作业数据,然后进行订阅。实现这一目标的最佳方法是什么?

以下是上面示例中获得的列表的外观:

[{uid: 'user1', name: "John", homework: {homeworkAnswer: "Sample answer"}}, {uid: 'user2', name: "Mario"}]

这是我对usershomework的两个观察值:

let usersObservable = this.af.getObservable(`users/`);
let hwObservable = this.af.getObservable(`homework/`);

1 个答案:

答案 0 :(得分:7)

基本上,您需要做两件事,但可能需要考虑一些细节。

  1. 从两个可观察对象获取数据。
  2. 将数据转换为所需的结果。

使用forkJoin可以轻松实现第一步。在forkJoin中,您可以传入多个可观察对象,并且所有可观察对象完成后它将发出一个值。 重要forkJoin仅在完成后发出。如果您的数据来自商店或主题,则可能必须添加take(1)运算符,这样才能真正完成。

转换部分也应该很容易。我假设您要拥有用户对象中存在的所有用户,因此我们可以使用Object.keys遍历现有用户键,然后使用map来转换数据。

// Imports:
import { forkJoin } from 'rxjs';
import { take } from 'rxjs/operators';

// Step 1: Use fork join to get the result from both observables
forkJoin(
    // pipe(take(1)) is only needed if the observables don't complete.
    usersObservable.pipe(take(1)), 
    hwObservable.pipe(take(1))
)
    // Step 2: Transform the data.
    // We now need to map our both results. We want to return all
    // users and add the homework if available. So we can user
    // Object.keys to iterate over the existing user keys in your object.
    .pipe(map(([users, homeworkMap]) => Object.keys(users)
        // Now we can map the keys to the actual user objects
        // and merge them with the homework
        .map(userKey => {
            const user = users[userKey];
            const homework = homeworkMap[userKey];
            return {
                ...user,
                homework
            };
        })
    ))
    .subscribe(users => console.log('Users: ', users));