2017-09-01 47 views
6

Używam kątowego 4 i próbuję uzyskać dane z 2 punktów końcowych, ale mam problem ze zrozumieniem rxjs.Angular 4 łączy dane z wielu żądań HTTP

przy pomocy tego kodu mogę uzyskać tylko listę studentów i użytkowników.

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()); 
    } 

Powiedzmy to dane: Student

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

użytkownika

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

Chcę dostać pierwsze wszyscy studenci następnie porównać identyfikator użytkownika, jeśli jest taka sama, jak użytkownik następnie łączę oba obiekty w jeden, dopóki nie otrzymam tablicy w następujący sposób:

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

Myślę, że powinienem użyć płaskiego planu, ale spróbowałem napisać kod, ale to nie działa dla mnie i nie znalazłem przykładu z taką logiką.

Czy możesz mi pomóc.

+0

flatmap pozwala na zmianę strumieni, na przykład możesz poprosić o uczniów, a następnie uzyskać listę kursów dla konkretnego ucznia, która byłaby dobrym rozwiązaniem n; w tym przypadku zawsze potrzebujesz obu list, a następnie możesz zrobić trochę logiki, więc możesz potrzebować forkjoin, scalić lub połączyć, aby to zrobić – David

Odpowiedz

2

Można użyć operatora switchMap (alias flatMap) w następującym kodzie:

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

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

0

Można spróbować wykonać następujące czynności:

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$; 
    }