【问题标题】:How to handle nested HTTP requests in Angular 7?如何在 Angular 7 中处理嵌套的 HTTP 请求?
【发布时间】:2019-07-31 05:10:03
【问题描述】:

我有一个从服务器获取数据的通用服务。收到响应后,我使用映射器函数将纯 JSON 数据映射到所需模型。对于映射器函数中的某些类类型,我需要从服务器获取一些额外的数据。如何强制映射器函数等待第二个请求?

这是我的get函数:

 getChildren(params: ITreeQueryParams): Observable<Optional<T[]>> {
    params.id = isPresent(params.id) ? params.id : 0;
    params.parentId = isPresent(params.parentId) ? params.parentId : 0;
    params.isRoot = isPresent(params.isRoot) ? params.isRoot : false;
    params.additionalId = isPresent(params.additionalId) ? 
    params.additionalId : 0;
    return this.http.get<IListResponse<T>>
(`${this.resourceUrl}/getChildren/${params.id}/${params.parentId}/${params.isRoot}/${params.additionalId}`,
      {
        observe: 'response'
      }).pipe(map((resp) => this.mapResponse(resp,this.model)));
  }

这是我的映射器函数:

 protected mapResponse(resp: any, model: IAsset): void {
    if (resp) {
      this.anotherTreeService.getNodeDetail(resp.id, resp.isRoot).subscribe(res => {
        model.additionalData = {canEdit: res.length > 0 ? true : false};
      });
      if (resp.name) {
        model.title = resp.name;
      }
    }
  }

【问题讨论】:

  • 使用mergeMap
  • RXJS 中的 Observable.combineLatest 或 Observable.forkJoin 更好

标签: angular httprequest angular7 fork-join


【解决方案1】:

RxJS 中有很多运算符可以实现您想要的。当数据模型本身不包含所有数据并且您需要单独调用以根据第一个结果检索其他数据时,您经常看到使用的是这样的示例:

this.myFirstService.getById(id).pipe(
   map(data => jsonToMyModel(data)),
   tap(model => this.data = model),
   switchMap(model => {
      return this.mySecondService.getListById(model.id)
   }),
   tap(secondData => this.data.list = secondData)
).subscribe()

这会改变您想要实现的目标,因为可以使用forkJoin()mergeMap() 将所有数据最终存储在 Observable 返回的一个模型中。在这些类型的情况下,这些运算符中的任何一个都有其用途。

希望这会有所帮助。要更清楚、更直接地说明您想要什么,您需要一个更完整的问题,其中包含一些您想要什么以及您尝试过的示例。

【讨论】:

    【解决方案2】:

    如果我理解正确,您只是想提出一个请求并为其提出子请求。

    为此,如果您需要接受许多子请求,您可以使用switchMapforkJoin

    这里是你如何重写你的代码(我会写一个简化版)

    getChildren() {
      this.http.someRequest.pipe(
        tap(response => {
            if (resp.name) {
              model.title = resp.name;
            }
        }),
        switchMap(response =>
            forkJoin(
                response.map(r => this.http.someRequest(r))
            )
        )
      )
    }
    

    switchMap 所做的是在每次源发射(您的第一个 observable)之后,它订阅回调中返回的 observable(如果它已经被订阅,它首先从回调 observable 中取消订阅)。

    forkJoinPromise.all 类似。您可以在那里传递一个数组、对象或多个可观察对象(现已弃用),并在订阅中获得一个数组或一个对象。

    请注意forkJoin 将发出每个可观察对象发出的最后一个值仅当所有可观察对象完成时。此外,如果任何 observable 完成而没有发出值 forkJoin 完成时也没有发出值。由于所有http.whatever 都是可观察的,其中一个next 和立即complete 之后您不必担心这一点。

    如果有任何可观察到的错误forkJoin 错误。

    【讨论】:

      猜你喜欢
      • 2018-11-27
      • 1970-01-01
      • 1970-01-01
      • 2016-09-14
      • 2019-07-04
      • 1970-01-01
      • 1970-01-01
      • 2021-10-03
      • 2015-04-11
      相关资源
      最近更新 更多