【问题标题】:How make secondary HTTP request based upon results of first如何根据第一个结果发出辅助 HTTP 请求
【发布时间】:2019-10-27 04:29:24
【问题描述】:

我有两个要尝试完成的异步请求,第二个基于第一个的结果。我尝试这样做的方式是:

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

我现在的方式确实成功地将它放入了我的 redux 商店。但是,由于它只是香草Array.map,因此它不会返回可观察值。这意味着 observable 没有存储在this.details$ 中,这意味着它不会在我的模板中使用{{ details$ | async | json }} 呈现

如何根据第一次 XHR 调用的结果实现第二次 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)
        );
      });
    })
  );
}

【问题讨论】:

  • 你能分享一下 details$ observable 的类型吗?是否可观察?

标签: javascript angular rxjs observable ngrx


【解决方案1】:

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

  1. 您的组件 [或您的守卫或解析器] 只会向商店发送一个操作。
  2. 如果您为该操作设置了减速器,那么您的减速器将首先被调用,否则将转到第 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

【讨论】:

    猜你喜欢
    • 2021-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-08
    • 1970-01-01
    • 2019-09-02
    相关资源
    最近更新 更多