Angular HttpClient Observable получает массив из вложенного хэша с pipe () и map () - PullRequest
0 голосов
/ 13 мая 2019

У меня есть некоторые проблемы с наблюдаемыми объектами RXJS и каналами, которые я не понимаю.

Мой 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: [массив из 11 пользовательских объектов]}, должен быть хэшем, где ключом является 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
    }, {}))

1 Ответ

1 голос
/ 13 мая 2019

Как @ 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 () работает так, как нужно, но в моем случае она не делаетили мало смысла делать это так.

...