Angular 4 merge data from multiple HTTP requests

I am using angular 4 and I am trying to get data from two endpoints, but I have a problem understanding rxjs.

With this code I can only get a list of students and users.

 getStudent() {
    return this.http.get(this.url + this.student_url, this.getHeaders()).map(res => res.json());
  }

getUsers() {
    return this.http.get(this.url + this.users_url, this.getHeaders()).map(res => res.json());
  }

Say this data: Student

[{"ID" : 1 , "SchoolCode": "A150", "UserID": 1 }, 
{"ID" : 5 , "SchoolCode": "A140" , "UserID": 3}, 
{"ID" : 9 , "SchoolCode": "C140" , "UserID": 4}]

User

[{"ID" : 1  ,"Name": "Rick" , "FamilyName" , "Grimes" },
{"ID" : 4 ,"Name": "Carle" , "FamilyName" , "Grimes" }]

I want to get all the students first, and then compare the UserID, if it is the same as the user, then I will combine both objects into one until I get such an array:

{"ID" : 1 , "SchoolCode": "A150","Name": "Rick" , "FamilyName" , "Grimes" }

I think I should use flatmap, but I really tried to write the code, but it does not work for me, and I did not find an example with such logic.

Could you help me.

+6
source share
2 answers

switchMap ( flatMap) :

// Observables mocking the data returned by http.get()
const studentObs = Rx.Observable.from([
  {"ID" : 1 , "SchoolCode": "A150", "UserID": 1 }, 
  {"ID" : 5 , "SchoolCode": "A140" , "UserID": 4}, 
  {"ID" : 9 , "SchoolCode": "C140" , "UserID": 3}
]);
const userObs = Rx.Observable.from([
  {"ID" : 1, "Name": "Rick" , "FamilyName": "Grimes" },
  {"ID" : 3, "Name": "Tom" , "FamilyName": "Cruise" },
  {"ID" : 4, "Name": "Amy" , "FamilyName": "Poehler" }
]);
// Return an observable emitting only the given user.
function getUser(userID) {
  return userObs.filter(user => user.ID === userID);
}

studentObs
  .switchMap(student => {
     return getUser(student.UserID).map(user => {
       // Merge the student and the user.
       return Object.assign(student, {user: user});
     })
  })
  .subscribe(val => console.log(val));

JSBin: http://jsbin.com/batuzaq/edit?js,console

+2

:

import { forkJoin } from 'rxjs/observable/forkJoin';

interface Student {
  id: number;
  schoolCode: string;
  userId: number;
}

interface User {
  id: number;
  name: string;
  familyName: string;
}

interface Merged {
  id: number;
  schoolCode: string;
  name: string;
  familyName: string;
}

getStudents(): Observable<Student[]> {
    // Implementation
  }

  getUsers(): Observable<User[]> {
    // Implementation
  }

  getMerged(): Observable<Merged[]> {
    const student$ = this.getStudents();
    const users$ = this.getUsers();
    const merged$ = forkJoin(student$, users$)
      .map(src => src[0].reduce((acc, current) => {
        // acc is the accumulated result (list with mapped objects)
        // current is an element of the students list
        const user = src[1].find(u => u.id === current.userId);
        // check if there is a user associated to the current student element
        if (user) { // if there is a matching user, push new element to result list
          acc.push({
            id: user.id,
            name: user.name,
            familyName: user.familyName,
            schoolCode: current.schoolCode
          });
        }
        return acc;
        // this could be changed to use a more immutable based approach
      }, new Array<Merged>()));
      // the seed value to start accumulating results is an empty list
    return merged$;
  }
0

All Articles