0

Suppose I have the following functions:

getUsers() {
  return Observable.of(['Adam', 'Eve'])
}

getUserPets(user) {
  return Observable.of(user === 'Adam' ? 'Adam pets' : 'Eve pets');
}

getUserKids(user) {
  return Observable.of(user === 'Adam' ? 'Adam kids' : 'Eve kids');
}

I would like to create function fetching users, their pets, kids and returning all that data as single object. Something like:

getUsersData() {
  // should return
  // [
  //    { user: 'Adam', pets: 'Adam pets', kids: 'Adam kids' },
  //    { user: 'Eve', pets: 'Eve pets', kids: 'Eve kids' }
  // ]
}

I tried to use combineLatest operator but my solution was really messy. What is the simpliest (or the most readable) way to implement such function?

sandbox: https://stackblitz.com/edit/angular-rspmy9?embed=1&file=app/app.component.ts

2 Answers 2

1

You can use forkJoin and concatMap for this:

import { Component } from '@angular/core';
import { concatMap, concatAll, map, toArray } from 'rxjs/operators';
import { of } from 'rxjs/observable/of';
import { forkJoin } from 'rxjs/observable/forkJoin';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  constructor() {}

  getUsers() {
    return of(['Adam', 'Eve'])
  }

  getUserPets(user) {
    return of(user === 'Adam' ? 'Adam pets' : 'Eve pets');
  }

  getUserKids(user) {
    return of(user === 'Adam' ? 'Adam kids' : 'Eve kids');
  }

  getUsersData() {
    return this.getUsers().pipe(
      concatAll(), // unpack the array of users
      concatMap(user => forkJoin(this.getUserPets(user), this.getUserKids(user)).pipe(
        map(([pets, kids]) => ({ user, pets, kids }))
      )),
      toArray(),
    );
  }
}

And then if you for example want to show this in a template you'll use:

{{ getUsersData() | async | json }}
Sign up to request clarification or add additional context in comments.

Comments

1

Using combineLatest is readable to me, though, I'm not sure what your implementation looked like.

function getUsers() {
  return Rx.Observable.of(['Adam', 'Eve'])
}

function getUserPets(user) {
  return Rx.Observable.of(user === 'Adam' ? 'Adam pets' : 'Eve pets');
}

function getUserKids(user) {
  return Rx.Observable.of(user === 'Adam' ? 'Adam kids' : 'Eve kids');
}

const users = getUsers().concatAll()
  .concatMap(user => Rx.Observable
    .combineLatest(getUserPets(user), getUserKids(user))
    .map(([pets, kids]) => ({user, pets, kids}))
  ).toArray();

users.subscribe(s => console.log(s));

jsbin example

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.