RxJs: объединить все значения после concapMap, чтобы они выдавались вместе в следующем событии подписки?

Я настроил наблюдаемое, чтобы в основном вызывать конечную точку для каждого элемента в массиве, но затем мне нужно объединить элементы перед публикацией для подписки «далее». Прямо сейчас подписка «далее» выполняется N раз в зависимости от суммы в массиве, есть идеи? Вот мой код

   from(items)
      .pipe(
        concatMap(item => {    
          return this.httpClient.get("https://randomuser.me/api/")
        }),
        tap(items => {
          debugger
        })
      )
      .subscribe(
        result => {
          debugger
        },
        error => {
          debugger
        }
      )

Я попытался поместить mergeAll перед TAP, но он вылетает.

Любые идеи ?

заранее спасибо


person Ian Gregson    schedule 08.05.2019    source источник
comment
используйте forkJoin() или toArray().   -  person martin    schedule 08.05.2019
comment
Как вы используете item под запросом HTTP?   -  person Ashish Ranjan    schedule 08.05.2019
comment
Элемент сейчас не используется в HTTP-запросе, это всего лишь тестовый URL-адрес. Но в конце концов в элементе есть идентификатор, и я вызову конечную точку, используя этот идентификатор.   -  person Ian Gregson    schedule 08.05.2019
comment
@martin использует forkJoin? Если я поставлю forkJoint после канала concatMap, это не сработает, у вас есть пример?   -  person Ian Gregson    schedule 08.05.2019


Ответы (1)


  • toArray() будет накапливать массив ответов,
  • reduce() можно использовать для воспроизведения поведения toArray() более гибким способом: вы можете применять более сложную логику слияния (например, игнорировать повторяющиеся записи и т. д.).

P.S. Не уверен, но может быть так, что вы что-то неправильно спроектировали. Вместо того, чтобы использовать накопление там, вы можете захотеть наблюдать более высокий порядок, чтобы ваш потребитель не требовал явного массива, а базовая логика была более развязанной.


Хорошо, дело в том, что вы можете думать, что toArray() — это совершенно частный случай редукции. Начнем с подписи: reduce(accumulator: function, seed: any): Observable. Таким образом, seed, второй параметр, является начальным значением, с которого вы начинаете (и в случае, если поток, который вы пытаетесь уменьшить, пуст, seed - это единственное значение, которое будет получено в результате). В случае toArray() seed это просто [] -... пустой... массив! Затем первый параметр, accumulator, это функция, которая принимает (result, current) - два параметра, где result представляет результат на данный момент, а current представляет "еще не уменьшенный" элемент потока. Таким образом, тип result равен array, а тип current может быть любым типом вашего потока, в вашем случае - ответы http, я думаю. (result, current) => { result.Add(current); return result; } - это самая простая возможная реализация, которая даст вам toArray() поведение. Однако вы можете сделать больше, например решить не добавлять current, если он устарел или недействителен, поэтому я сказал вам, что reduce() намного мощнее.

П.П.С. Если вы хотите знать, насколько глубока кроличья нора, то reduce (также известный как foldl в Haskell и других функциональных языках) в основном является шаблоном рекурсии. Большинство вещей (но определенно не все!), определенных с помощью рекурсии, можно переписать как reduce с соответствующими параметрами seed и accumulator; например, довольно легко реализовать filter сквозное сокращение. См. этот вопрос, чтобы узнать больше.

person Sereja Bogolubov    schedule 08.05.2019
comment
Спасибо! У вас есть пример с сокращением? Я пробовал toArray, и это, кажется, работает. - person Ian Gregson; 08.05.2019