Angular HttpClient Observable 使用 pipes() 和 map() 从嵌套散列中获取数组

Angular HttpClient Observable get array from nested hash with pipes() and map()

我对 RXJS Observables 和管道有一些我不理解的问题。

我的APIreturn是这样的回复

    {
      "_embedded": {
        "users": [
          {
             "id": 1,
             "username": "steve"
          }
        ]
      }
    }

我有以下功能(对于这个问题非常简化):

  listUsers() {
    return this.http.get<Users>(API_BASE_URL + '/v1/users').pipe(map(u => u._embedded.users))
  }

  getFirstUser() {
    return this.listUsers().pipe(first())
  }

  listUsersById() {
    return this.listUsers().pipe(reduce((acc, user) => { 
      acc[user.id] = user
      return acc
    }, {}))
  }

我是这样测试的:

this.listUsers().subscribe(data => {
  console.log("FUNC: listUsers()")
  console.log(data)
  console.log(data[0])
})

this.listUsersById().subscribe(data => {
  console.log("FUNC: listUsersById()")
  console.log(data)
  console.log(data[0])
})

this.getFirstUser().subscribe(data => {
  console.log("FUNC: getFirstUser()")
  console.log(data)
})   

listUsers() 做我期望的事情,注销 11 个用户对象的数组,然后注销数组中的第一个用户对象。

listUsersById() logs out { undefined: [array of 11 user objects] }, 应该是一个散列,其中键是 id,值是用户对象。

getFirstUser() 登出一个包含 11 个用户对象的数组(应该是一个)

问题似乎是 rxjs 没有将 listUsers() 中的 return 值视为数组 "internally",这使得我的管道函数无法使用。

我想要的是创建 "data pipeline" 直到需要时才解析函数。使用 return 承诺的 Angular HTTPClient 时,我应该如何正确执行此操作?

如果我解析了 http 请求并在数组中提供了可用数据,它就可以正常工作。:

from([
      {
        id: 1,
        username: "steve"
      },
      {
        id: 2,
        username: "jane"
      }
    ]).pipe(reduce((acc, user) => {
      acc[user.id] = user
      return acc
    }, {}))

正如@jb-nizet 在他的评论中解释的那样,该事件只发出一次。

基于此,解决 listUsersById() 的一个简单实现是这样的:

  listUsersById() {
    return this.listUsers().pipe(map(u => u.reduce((acc, user) => { 
      acc[user.id] = user
      return acc
    }, {})))
  }

另一种选择是使用 flatMap() 为数组中的每个项目发出一个事件,如下所示:

  listUsers() {
    return this.http.get<Users>(API_BASE_URL + '/v1/users').pipe(map(u => u._embedded.users), flatMap(x => x))
  }

这样 getUsersById() 的原始实现可以按需工作,但在我的情况下,这样做没有意义或意义不大。