2016-07-22 49 views
2

尋求與可觀察到的HTTP請求序列,我希望有兩個HTTP調用的API,第二取決於第一。第一個返回一個Url數組,第二個返回該數組中每個url的請求,然後返回流中的響應。如果我硬編碼像,所以我回來了變化的要求的一個標題之一,我在尋找:角2鏈接的HTTP GET與幫助,可迭代陣

search(character): Observable<any> { 
let that = this 
let queryUrl: string = character.url; 
return this.http.get(queryUrl) 
    .map((response: Response) => { 
    this.characterResults = response.json().films 
    return this.characterResults 
     //Example response: 
     // ["https://api.com/films/1", "https://api.com/films/2", "https://api.com/films/3", "https://api.com/films/4"] 
    }) 
    .flatMap((film) => { 
    return that.http.get(film[0]) 
    .map((response: Response) => { 
     return response.json().title 
    }) 
    }) 
} 

getApiData(character) { 
    this.apiService.search(character) 
    .subscribe((results) => { // on sucesss 
      console.log(results) 
     }, 
     (err: any) => { // on error 
      console.log(err); 
     }, 
     () => { // on completion 
      console.log('complete') 
     } 
    ); 

但任何企圖使用的forEach在該數組迭代,然後讓所有的HTTP調用給我這個錯誤:

browser_adapter.js:84 EXCEPTION: TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined 

理想情況下,我想一個優雅的方式,使在第一次調用的結果陣列並行的後續調用,但我似乎無法找出哪些rxJs的幾十種方法可以幫助我做到這一點。任何人都可以給我任何幫助嗎?

+0

'flatMap'應該返回Observable,但是你的代碼不會返回任何東西。也許這就是問題所在。 –

+0

代碼已經更新,你的當前位置對 –

回答

5

兩種方式,如果您希望每個結果進行單獨流然後flatMap是你的朋友。你可以用它來拉平任何事情,ArraysPromises,或Observables。你的情況,你可以通過做起來鏈要求:

search(character): Observable<any> { 
    return this.http.get(character.url) 
    .flatMap((response: Response) => response.json().films) 
    .flatMap((film: string) => this.http.get(film), 
      (_, resp) => resp.json().title) 
} 

getApiData(character) { 
    this.apiService.search(character) 
     .subscribe((results) => { // on sucesss 
      //Called for each url result 
      console.log(results) 
     }, 
     (err: any) => { // on error 
      console.log(err); 
     }, 
     () => { // on completion 
      console.log('complete') 
     } 
    ); 

或者您可以使用forkJoin而是返回結果

return this.http.get(character.url) 
    .flatMap((response: response) => 
      //Waits until all the requests are completed before emitting 
      //an array of results 
      Observable.forkJoin(response.json().files.map(film => 
       this.http.get(film).map(resp => resp.json().title) 
      )); 

編輯陣列1

爲了解決第二個參數flatMap更完全。它是一個函數,它接收傳遞給第一個選擇器方法的原始值與來自展平操作的結果配對。那就是說,如果選擇器1收到a並返回的[1, 2, 3]。第二個選擇器將被調用3次,參數(a,1),(a,2)和(a,3)。

如果你想獲得多個值我會建議你使用輔助映射操作,以保持流潔淨,但它是由你。

.flatMap((film: string) => this.http.get(film), 
     (film: string, resp: Response) => resp.json()) 
//Typescript's destructuring syntax, extracts the values you want 
//and creates a new object with only those fields 
.map(({date, title}) => ({date, title})); 
+0

謝謝!第一個案例符合我的用例,非常優雅,而且很有效。但我不確定我是否理解了第二個flatMap。 '.flatMap((電影:字符串)=> this.http.get(膜), (_,RESP)=> resp.json()標題) }'什麼'(_,RESP)'做什麼?而且我不確定我是否理解你是如何使用逗號映射http返回的,語法令我感到困惑。 –

+0

'flatMap'需要兩個參數,第一返回一個對象爲平坦和第二從所述扁平源取單獨的值和對它們施加的映射。在這種情況下,它會從每個HTTP調用中獲取響應,並從響應值中提取標題。 – paulpdaniels

+0

謝謝保羅!如果我想從對象中提取標題和日期,並輸出如下所示的對象數組:[{title:'resp.json()。title',date:'rsp.json()。date'},{ title:'title,date:'date'}],我可以使用* ngFor在組件中顯示異步,這可能嗎? –