2017-08-03 32 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