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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.