2017-09-01 58 views
6

我正在使用角4,我試圖從2個端點獲取數據,但我對rxjs有一個理解問題。角4結合來自多個HTTP請求的數據

使用此代碼我只能獲取學生和用戶列表。

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

比方說,這是數據: 學生

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

用戶

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

我想首先是學生,然後比較用戶名,如果是一樣的用戶然後我結合了對象合併爲一個,直到我得到這樣一個數組:

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

我想我應該使用flatmap,但我確實嘗試寫代碼,但它對我沒有用,我沒有找到這樣的邏輯例子。

你能幫我嗎。

+0

flatmap允許您更改流,例如,您可以要求學生,然後獲得特定學生的課程列表,這將是一個很好的選擇N;在這種情況下,你總是需要兩個列表,然後你可以做一些邏輯,所以你可能需要forkjoin,merge或combine來做 – David

回答

2

您可以在下面的代碼使用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

0

你可以嘗試以下方法:

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