2017-08-03 179 views
1

我想重構一組使用forkJoin工作的服務調用。我有一些來自ngrx商店的商品<>,我需要爲每件商品進行一次http調用)。需要幫助將rxjs forkjoin調用轉換爲異步調用(在ngrx @Effect中)

問題w/forkjoin是它本質上是一個阻塞操作,所以我需要等待所有的調用完成之前它返回 - 它可能是一個長長的列表。

我希望調用是異步的 - 這樣循環每個項目,調用服務,並返回結果,以便UI更新項目。 (爲了使事情變得複雜了一點,這是一個包裹NGRX @Effect內)

這是我工作的代碼:

@Effect() 
    loadItemValues$: Observable<Action> = this.actions$ 
     .ofType(setActions.LOAD_ITEMS_DATA) 
     .map(toPayload) 
     .switchMap(key => { 
      return this.store.select(fromRoot.getItems) 
       .flatMap(items => { 
        let observables = new Array(); 
        for (let i of items) { 
         observables.push(this.myService.getItemInfo(i, key)); 
        } 
        return Observable.forkJoin(observables) 
        .map((res: Grades[]) => { 
         return new setActions.LoadValuesSuccessAction(res); 
        }) 
       }) 
     }) 

我假設我需要創建一個新的觀察到的,再次使用flatmap,但弄清楚如何將鏈傳遞回去,以確保每個項目都調用服務,然後調用LoadValuesSuccessAction Reducer和結果。

任何幫助,將不勝感激。

+0

所以你想要一個接一個地發出的值,每個都在'LoadValuesSuccessAction'中 - 每個動作都包含一個數組,其中包含一個值? – cartant

+0

@cartant是正確的。成功動作設置狀態(通過減速器) – user58210

回答

2

變化很小。所有你應該需要做的是替換此:

return Observable.forkJoin(observables) 
.map((res: Grades[]) => { 
    return new setActions.LoadValuesSuccessAction(res); 
}) 

與此:

return Observable.merge(...observables) 
.map((res: Grades) => { 
    return new setActions.LoadValuesSuccessAction([res]); 
}) 

而不是使用forkJoin的,只是使用merge。這將看到單個Grades排放(只要它們可用),而不是一個Grades[]。您還需要將收到的res包裝在一個數組中,因爲您的動作創建者可能會接受Grades[]參數。

+0

感謝cartant--看起來像是在工作。快速的問題,橢圓是做什麼的? – user58210

+0

這是[數組擴展語法](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Spread_operator#Spread_in_array_literals)。許多RxJS方法接受多個可觀察參數,並且在傳遞多個參數時它們的行爲一致。然而,有些函數在傳遞數組時的行爲不同(例如'forkJoin'將數組參數視爲多個可觀察參數,但'concat'不會 - 它將數組視爲['ObservableInput'](http:// reactivex .io/rxjs/class/es6/MiscJSDoc.js〜ObservableInputDoc.html)),所以我喜歡使用擴展語法來保持一致性。 – cartant