2017-01-22 146 views
0

我使用rxjs做出幾個HTTP請求和我想的對象,看起來像落得:多RxJS Ajax請求

{ 
    100: { 
    ...response from api call... 
    }, 
    205: { 
    ...response from api call... 
    }, 
    ...etc... 
} 

這是我到目前爲止有:

const projectIds = [100, 205, 208, 300] 
const source = Rx.Observable 
    .from(projectIds) 
    .flatMap(id => get(`projects/${id}/builds`)) 
    .map(response => response['data']) 
    .zip(projectIds) 
    .toArray() 

source.subscribe(pipelines => { 
    console.log(pipelines) 
}) 

這給了我一個數組的數組,其中第一個元素是來自調用的響應,第二個元素是項目的ID。

問題是響應與項目ID不匹配,因爲響應以不同順序返回,具體取決於哪個請求首先完成。

如何保持順序(或至少知道哪個projectId與每個響應一起),同時最後還有一個對象(當前是一個數組)?

回答

1

只需使用flatMapelementSelector超載:

.flatMap(
    projectId => getProjectDetails(projectId), 
    (projectId, details) => ({ id: projectId, details }) 
) 

function getProjectDetails(id){ 
    return get(`projects/${id}/builds`) 
    .map(response => response['data']); 
} 

這樣可以讓您根據需要組合輸入參數和flatMap的每個輸出值,從而有效地保留上下文。如果您要求輸出訂單保持不變,您可以使用.concatMap,但是所有排放都是在相互之間完成,而不是同時完成。

後來總算用.reduce的所有對象合併回一個大的排放:

.reduce((acc, curr) => acc[curr.id] = curr.details, {}) 
2

選項1

Instread的flatMap你可以使用concatMap,應保持秩序。

注意:雖然這不會產生任何併發請求,但如果這是您正在尋找的。


選項2

如果你想併發請求(在從RxJS側至少,根據不同的瀏覽器,這可能仍然是有限的),你可以使用使用forkJoin類似下面的一些結構:

const projectIds = [100, 205, 208, 300] 
const source = Rx.Observable 
    .from(projectIds) 
    .map(id => get(`projects/${id}/builds`).pluck('data')) 
    .toArray() 
    .switchMap(requestArray => Rx.Observable.forkJoin(requestArray)) 
    .zip(projectIds) 


source.subscribe(pipelines => { 
    console.log(pipelines) 
})