【问题标题】:Angular RxJs level up during looping an arrayAngular RxJs 在循环数组期间升级
【发布时间】:2019-03-25 14:53:36
【问题描述】:

我有一个 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。 有人可以帮我解决这个问题吗?:)

【问题讨论】:

  • 请把你的代码放在 ``` lang-js 和 ``` 之间以获得更好的可读性。详情见"formatting help"
  • 这可能会有所帮助:stackoverflow.com/a/53109081/9386929
  • @nircraft,我已经检查了文章,但我无法理解你的意思,这篇文章对我有什么帮助((((也许,你可以向我提供你的答案的更多细节?我收到新数据,但我无法获得初始数组,因为流给了我最后一个流元素。

标签: angular http rxjs


【解决方案1】:

主要技巧是使用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 是主要技巧。

希望对你有帮助

【讨论】:

  • 这真的很有帮助和相关的答案。为我的类似用例工作
【解决方案2】:

如果我做对了,你需要做的是:

  • 从后端获取初始数组
  • 对于数组的每个元素,调用getSomeInfo 并将结果(应该是一个数组)存储到specialProp 属性中
  • 然后,对于specialProp 数组中的每个条目,您要调用getSomeOtherInfo 方法,获取更多数据并将其存储到名为anotherSpecialProp 的属性中

如果这一切都是真的,那么你可以尝试这些方法

getArray()
.pipe(
    mergeMap(mainArray => mainArray),  // unwind the array received
    switchMap(mainItem => getSomeInfo(mainItem.id) // fetch the first set of info from backend
        .pipe(
            tap(someInfo => {
                mainItem['specialProp'] = someInfo; // wrote someInfo into specialProp property
            }),
            mergeMap(specialProps => specialProps), // unwind the array of specialProps
            switchMap(specialProp => getSomeOtherInfo(specialProp.name) // for each specialProp fetch the additional data
                .pipe(
                    tap(someOtherInfo => {
                        specialProp['anotherSpecialProp'] = someOtherInfo // store additional data into anotherSpecialProp property
                    })
                )
            ),
            toArray(), // rewind the array of  specialProps and return it
            map(() => mainItem)
        )
    ),
    toArray() // rewind the array of mainItems and return it
)

您可能需要注意的是 mergeMap 与数组一起使用,例如mergeMap(mainArray => mainArray).

mergeMap 接受一个返回 ObservableInput 的函数作为输入。 Array 是一个 ObservableInput,它会在 完成 之前同步发出其所有项目。因此,将返回 Array 的函数传递给 mergeMap 意味着发出 Array 的所有元素。

您可以找到above example here 的示例

【讨论】:

  • 非常感谢你们,伙计们!你的回答很有用!它让我对 RxJs 有了一些了解,因为我是 RxJs 的新手,也是深入了解这个库的一步!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-08
  • 1970-01-01
  • 1970-01-01
  • 2018-10-27
  • 1970-01-01
相关资源
最近更新 更多