【问题标题】:Angular HttpClient Observable get array from nested hash with pipes() and map()Angular HttpClient Observable 使用管道()和映射()从嵌套哈希中获取数组
【发布时间】:2019-05-13 16:56:21
【问题描述】:

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

我的 API 返回这样的响应

    {
      "_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() 注销 { undefined: [array of 11 user objects] },应该是一个哈希,其中键是 id,值是用户对象。

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

问题似乎是 rxjs 没有将 listUsers() 的返回值视为“内部”数组,从而使我的管道函数无法使用。

我想要的是创建“数据管道”而不解析函数,直到需要。使用返回承诺的 Angular HTTPClient 时,我应该如何正确执行此操作?

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

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

【问题讨论】:

  • 你的 listUsers() 方法返回一个 Observable >。它发出一个且只有一个事件,即用户数组 (Array)。最后你的 from() 调用做了一些完全不同的事情。它创建了一个 Observable。这个 observable 发出两个事件,每个事件都是一个用户。您可以将其视为包含两个附件的电子邮件和两封电子邮件(每封包含一个附件)之间的区别。
  • 例如,您的 getFirstUser() 没有任何意义:在只发射一次的 observable 上使用 first 运算符不会做任何有用的事情。如果要将 Observable> 转换为 Observable,那么正确的运算符是 map(array -> array[0])。
  • 太好了,谢谢你的回答!当你这样解释时,现在完全有道理了。

标签: angular ionic-framework rxjs ionic4


【解决方案1】:

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

基于此,解决 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() 的原始实现可以按需要工作,但在我的情况下,这样做没有意义或意义不大。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-22
    • 2011-10-04
    • 2019-06-02
    • 2011-03-31
    • 2015-10-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-08
    相关资源
    最近更新 更多