Наблюдаемый поток, значения которого обогащены другими, одноразовыми наблюдаемыми объектами

У меня есть вспомогательная функция, которая выполняет вызов API и возвращает массив items. Каждый из этих элементов представляет собой сущность, скажем, User.

У каждого пользователя есть свойство category_id, которое по умолчанию имеет значение NULL. Я хотел бы заполнить это свойство для каждого пользователя из результата другой вспомогательной функции, которая принимает идентификатор пользователя и возвращает Observable объекта Category, из которого я могу извлечь идентификатор, который будет использоваться в качестве атрибута category_id пользователя. .

Я получил следующий (псевдо) код (синтаксис TypeScript, но вопрос применим к наблюдаемым операторам в целом):

this.backend
    .request(
      'v1/users',
    )
    .pipe(
      map(items => {
        items.forEach(user => {
          this.categories.getName(user['id']).subscribe(category => {
            user['category_id'] = category['id'];
          });
        });
        return items;
      })
    )

Естественно, это не работает, потому что в нем смешиваются наблюдаемые операторы с функциями массива (forEach).


person Dzhuneyt    schedule 26.02.2019    source источник


Ответы (1)


Вы не должны подписываться на наблюдаемое в трубе. Это антипаттерн. Используйте свой более высокий наблюдаемый и mergeMap с combLatest, чтобы получить то, что вы хотите:

this.backend
.request(
  'v1/users',
)
.pipe(
  mergeMap(items => {
    const requestUserWithCatArray = items.map(user => this.categories.getName(user['id']).pipe(
        map(category => {
             user['category_id'] = category['id'];
             return user;
        })
    ));
    return combineLatest(requestUserWithCatArray);
  })
);

Он вернет массив пользователей с их категорией.

person Quentin Fonck    schedule 26.02.2019
comment
Вы можете использовать forkJoin вместо combineLatest для выполнения запросов параллельно, а не последовательно (при условии, что this.categories.getName(user['id']) завершено). - person frido; 26.02.2019
comment
forkJoin может быть лучше в этом случае, да. - person Quentin Fonck; 27.02.2019