2017-02-27 42 views
8

我的後端在RxJS 5 Observable(我正在使用Angular 2)中經常返回數據作爲數組。RxJS內部數組「變平」的最佳方法Observable

我經常發現自己想要過程中的數組項單獨與RxJS運營商我用下面的代碼(JSBin)這樣做:

const dataFromBackend = Rx.Observable.of([ 
    { name: 'item1', active: true }, 
    { name: 'item2', active: false }, 
    { name: 'item3', active: true } 
]); 

dataFromBackend 
    // At this point, the obs emits a SINGLE array of items 
    .do(items => console.log(items)) 
    // I flatten the array so that the obs emits each item INDIVIDUALLY 
    .mergeMap(val => val) 
    // At this point, the obs emits each item individually 
    .do(item => console.log(item)) 
    // I can keep transforming each item using RxJS operators. 
    // Most likely, I will project the item into another obs with mergeMap() 
    .map(item => item.name) 
    // When I'm done transforming the items, I gather them in a single array again 
    .toArray() 
    .subscribe(); 

mergeMap(val => val)行不會覺得很地道。

有沒有更好的方法將變換應用到由Observable發出的數組的成員?

注意:我希望RxJS操作符(vs數組方法)能夠轉換我的項目,因爲我需要能夠將每個項目投影到第二個可觀察項中。典型用例:項目id的列表後端返回,我需要從後端請求所有這些項目。

回答

6

您可以使用concatAll()mergeAll()而不帶任何參數。

dataFromBackend 
    .do(items => console.log(items)) 
    .mergeAll() // or .concatAll() 

本(包括mergeMap)只在RxJS 5,因爲它把觀測量,陣列,陣列狀物體,承諾等的方法相同。

最終,你也可以這樣做:

.mergeMap(val => Observable.from(val) 
    .do(item => console.log(item)) 
    .map(item => item.name) 
) 
.toArray() 
+0

謝謝,馬丁。 concatAll()會保留原始數組中項目的順序並且「mergeAll()」不會保持正確? – AngularChef

+2

@AngularFrance由於您要解包一個數組,因此您使用哪一個都不重要,並且都會生成訂購商品。這僅在與異步操作一起使用時纔有用,這不是這種情況。 – martin

1

如果它是一個同步操作,我建議使用JavaScript的Array.map相反,它甚至應該節省一些性能:

const dataFromBackend = Rx.Observable.of([ 
    { name: 'item1', active: true }, 
    { name: 'item2', active: false }, 
    { name: 'item3', active: true } 
]); 

dataFromBackend 
    .map(items => items.map(item => item.name)) 
    .subscribe(); 
+0

這就是事情,更多的時候我發現自己將每個項目投射到第二個可觀察項中。典型用例:項目id的列表後端返回,我需要從後端請求所有這些項目。我應該在我的問題中包括這一點。 – AngularChef

+0

這確實對於如何構建你的流有所作爲 - 但在這種情況下,你可能更喜歡@ martin的答案 - 儘管我必須在這裏做一個個人(略有不相關的)評論:它通常是一個糟糕的REST架構首先請求一個ID列表,然後在單獨的休息呼叫中分別獲取他們的詳細信息 - 這對任何服務器來說都只是一種折磨,而且通常比單純的首次呼叫檢索所有數據要花費更多的時間。 – olsn

+0

當然。但正如你所知道的,我們有時只是API的消費者*,而不是它的*創造者*。就在最近,我遇到了我剛剛描述的用例(必須單獨調用密鑰列表,然後用於實體本身)和Gmail JavaScript API。 – AngularChef

0

其實如果你只需要在流內使用它:

.flatMap(items => of(...items))