简体   繁体   English

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

[英]Combine RXJS observable results into one

I have two nodes in my database: 我的数据库中有两个节点:

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

Some users might or might not have a homework. 有些用户可能有功课,也可能没有。

I want to obtain a list of all users with each user's homework data with a single call and subscribe. 我想通过一次调用就获得所有用户的列表以及每个用户的作业数据,然后进行订阅。 What would be the best way to achieve this? 实现这一目标的最佳方法是什么?

Here is how the list obtained should look like for the example above: 对于上面的示例,获得的列表如下所示:

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

These are my two observables for users and homework : 这是我对usershomework两个观察值:

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

Basically you need to do two things, but there might be some details to consider. 基本上,您需要做两件事,但是可能需要考虑一些细节。

  1. Get the data from both observables. 从两个可观察对象获取数据。
  2. Transform the data to your desired result. 将数据转换为所需的结果。

The first step can easily be achieved by using forkJoin . 第一步可以通过使用forkJoin轻松实现。 In forkJoin you can pass in multiple observables and it will emit a value as soon as all observables have completed. forkJoin您可以传入多个可观察对象,并且所有可观察对象完成后它将发出一个值。 Important: forkJoin only emits after completion. 重要提示: forkJoin仅在完成后发出。 If your data comes from a store or a subject, you might have to add a take(1) operator so it actually completes. 如果您的数据来自商店或主题,则可能必须添加take(1)运算符,这样它才能真正完成。

The transformation part should be easy as well. 转换部分也应该很容易。 I assume you want to have all users that exist in the user object, so we can use Object.keys to iterate over the existing user keys and then use map to transform the data. 我假设您要拥有用户对象中存在的所有用户,因此我们可以使用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));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM