如何根据第一个

时间:2019-06-12 15:39:51

标签: javascript angular rxjs observable ngrx

我有两个要处理的异步请求,第二个基于第一个的结果。我尝试执行此操作的方法是:

  1. 聆听第一个操作是否成功:actions.GetAllItems
  2. 根据ID this.store.select(selectors.getItemsById)从商店中选择相关项目
  3. 映射返回的ID,以便我可以对第一次调用返回的ID数组中的每个项目进行第二次调用
  4. 将结果放入redux存储中,以呈现给视图。

我现在的方式成功地将其放入我的redux存储中。但是,由于它只是普通Array.map,因此不会返回可观察到的结果。这意味着该可观察对象未存储在this.details$中,这意味着它未使用{{ details$ | async | json }}

呈现在我的模板中

如何根据第一个XHR调用的结果来完成此操作?


ngOnInit() {

  this.store.dispatch(new actions.GetAllItems())

  this.details$ = this.actions$.pipe(
    ofType(actions.types.GetAllItemsSuccess),
    mergeMap(() => {
      return this.store.select(selectors.getItemsById); // filter to multiple items based on item ID
    }),
    map((items: models.IItemGeneralResponse[]) => {
      items.map(item => { // sync map does not seem like it belongs in rxjs
        this.store.dispatch(
          new actions.GetItemDetail(item.id)
        );
      });
    })
  );
}

1 个答案:

答案 0 :(得分:0)

您正在尝试在角度组件中进行ngrx效果处理。使用效果来处理副作用(调用后端/从本地存储中获取数据等),并使组件通过选择器监视状态的一部分。让我们总结一下-

  1. 您的组件[或您的守卫或解决者]只会向商店发送操作。
  2. 如果您为此操作设置了一个reducer,那么将首先调用您的reducer,否则将转到第3步
  3. 实际上,您正在监视调度的动作。您的效果将进行第一个调用,然后从第一个调用的响应开始,将进行第二个调用,然后它将通过分派该组件来监视组件正在监视的商店中的状态(或状态的一部分)。各自的动作。

这是典型的工作流程[可能会根据应用程序的需要而有所不同,但基本思路保持不变]。因此,保留基本思想就可以像这样修改您的代码-

在您的组件中

sliceOfState$: Observable<any>; //change the type of observabe as per your app

  ngOnInit() {

    this.store.dispatch(new actions.GetAllItems())

    //this observable will be used to render your data on UI
    //you can use various rxjs operators to transform your data before shoing to UI
    this.sliceOfState$ = this.store.select(//your selector which gives you sliceOfState);
  }

现在生效-

@Effect()
  this.details$ = this.actions$.pipe(
    ofType(actions.types.GetAllItems),
    switchMap(() => {
      //here you call API which makes the call to backend which return allItems
      return this.yourServiceWhichGetAllItems.getAllItems();
    }),
    switchMap(allItems => {
      //now for each item you need to get its detail
      //so forkJoin all the observables which calls the backedn for each item
      const obs$ = allItems.map(item => this.yourServiceWhichGetDetails.getItemDetail(item));
      return forkJoin(obs$);
    })
    map(allItemsWithDetails => {
      //here you should call your action which will update the state in your store
      return new actions.SetAllItemsDetails(allItemsWithDetails);
    })    
  );

我提供了伪代码,它将使您了解如何实现自己的目标。有关更多信息,您可以访问ngrx的官方网站-https://ngrx.io/guide/effects