最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Combine RXJS observable results into one - Stack Overflow

programmeradmin3浏览0评论

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:

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

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:

let usersObservable = this.af.getObservable(`users/`);
let hwObservable = this.af.getObservable(`homework/`);
Share Improve this question edited Sep 4, 2018 at 13:52 Smitherson asked Sep 4, 2018 at 13:45 SmithersonSmitherson 4331 gold badge6 silver badges12 bronze badges 7
  • Please be more exact with your terminology. Nowhere in your code you have a list. You ask for a list in your question but your example on how the result should look is an object. Which one do you need? – tom van green Commented Sep 4, 2018 at 13:50
  • So hwObservable returns all homeworks for all users? – martin Commented Sep 4, 2018 at 13:50
  • @tomvangreen I have edited my answer. – Smitherson Commented Sep 4, 2018 at 13:51
  • @martin Yes, and this.af.getObservable('homework/${user.uid}'); obtains the homework for a specified user. – Smitherson Commented Sep 4, 2018 at 13:52
  • Thanks. There is still a little error in your example. Lists don't have properties. If you need a list you need to remove user1: and user2: from the result and only have the objects ( [{}, {}] ) – tom van green Commented Sep 4, 2018 at 13:52
 |  Show 2 more ments

1 Answer 1

Reset to default 7

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. In forkJoin you can pass in multiple observables and it will emit a value as soon as all observables have pleted. Important: forkJoin only emits after pletion. If your data es from a store or a subject, you might have to add a take(1) operator so it actually pletes.

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.

// 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 plete.
    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));
发布评论

评论列表(0)

  1. 暂无评论