首页 > 解决方案 > Angular RxJs 在循环数组期间升级

问题描述

我有一个 http get 请求来获取一个类似的数组

[
  {name: 'name1', id: 1, specialProp: [] },
  {name: 'name2', id: 2, specialProp: [] }
]

我需要获取每个数组项,获取一个 id 并向服务器发送请求以获取一些信息。结果应写入属性specialProp。之后,我需要获取道具的数组,specialProp并为每个项目获取一些数据,将其放入anotherSpecialProp. 最后我应该有最终的数组

[
  {name: 'name1', id: 1, specialProp: [
    {name: 'c', anotherSpecialProp: []}, 
    {name: 'd', anotherSpecialProp: []}
  ]},

  {name: 'name2', id: 2, specialProp: [
    {name: 'a', anotherSpecialProp: []},
    {name: 'b', anotherSpecialProp: []}
  ]}
]

我有代码:

this.http.get(url)
  .pipe(
    switchMap((mainItemArr: any) => from(mainItemArr)),
    mergeMap((mainItem: any): any => {
      return this.getSomeInfo(mainItem.Id) //another http get request
        .pipe(
          map((data: any): any => {
            return Object.assign(mainItem, { specialProp: data })
          }),
          switchMap((mainItemArr: any): any => from(mainItemArr.specialProp)),
          concatMap((item: any): any => {
            return this.getSomeOtherInfo(item.Id) // one more http get request
              .pipe(
                map((data: any): any => Object.assign({}, task, { anotherSpecialProp: data }))
              )
          }),
        )
    })
  )

所以在订阅中我只收到项目,而不是整个 mainItemArr。有人可以帮我解决这个问题吗?:)

标签: angularhttprxjs

解决方案


主要技巧是用于map将范围属性与请求结果合并。

这是一个粗略的示例,如何在第一级 ( ) 中实现这一点specialProp

this.http.get(url).pipe(
  mergeMap(mainItemArr => {
    // forkJoin will wait for each request to complete
    return forkJoin(
      // make a subsequent request for each item in mainItemArr
      mainItemArr.map(mainItem => {
        return this.getSomeInfo(mainItem.Id).pipe(
          // merge getSomeInfo result with the mainItem
          map(someInfo => {
            return {
              ...mainItem,
              specialProp: someInfo
            };
          })
        )
      })
    )
  })
)

对于anotherSpecialProp请求——你需要更深一层。

在现实世界的应用程序中,我建议将这些后续调用拆分为单独的函数/方法。

注意

您不需要将数组转换为 Observable:

mergeMap(mainArray => mainArray)

相反,您可以将其保留在 JS 范围内并在 中执行后续请求mergeMap,例如:

mergeMap(mainArray => {
  // making sub requests here
})

使用mergeMap将数组转换为 Observable 也应该有效,尽管在深入 1 级时可能会更加混乱,恕我直言。无论如何,这map是主要的伎俩。

希望这可以帮助


推荐阅读