Объедините наблюдаемые результаты RXJS в один - PullRequest
0 голосов
/ 04 сентября 2018

В моей базе данных есть два узла:

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"}]

Это мои две наблюдаемые для users и homework:

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

1 Ответ

0 голосов
/ 04 сентября 2018

В основном вам нужно сделать две вещи, но могут быть некоторые детали для рассмотрения.

  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));
...