Гибрид mergeMap и concatMap в rxjs

Я работаю над одним внутренним приложением, и у меня есть ситуация, когда я получаю события от пользователей. Для каждого события я буду звонить в какую-то конечную точку foo. Если у меня есть несколько событий от одного и того же пользователя, я хочу выполнить следующий вызов foo после завершения предыдущего вызова foo (поведение concatMap). В то же время для разных пользователей вызовы должны выполняться параллельно (поведение mergeMap).

В коде это выглядит примерно так:

const userEvent$: Observable<{userId: string}> = ...
const foo: (userId: string) => Observable<Response> = ...

let result$: Observable<Response> = ???
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
81
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Рассмотрите возможность использования оператора GroupBy для группировки событий по userId, затем примените concatMap к группе, чтобы события в одной группе выполнялись последовательно, как показано в примере ниже:

 userEvent$.pipe(
           groupBy(item => item.userId),
           mergeMap(group => group.pipe(concatMap(x => foo(x.userId))))
  );

Демо:

const { of, from } = rxjs;
const { delay, tap, concatMap, mergeMap, groupBy } = rxjs.operators;

function foo(userId, index) {
  return of(userId).pipe(
    delay(2000),
    tap(() => console.info("UserId: ", userId, ", Occurrences: ", index + 1))
  )
}


const userEvent$ = from([
  { userId: 1 }, // <- first 
  { userId: 2 }, // <- first 
  { userId: 2 }, // <- second 
  { userId: 3 },// <- first  
  { userId: 1 }, // <- second 
  { userId: 1 }, // <- third 
  { userId: 2 }, // <- third 
  { userId: 3 }, // <- second            
]);

userEvent$
  .pipe(
    groupBy(x => x.userId),
    mergeMap(group => group.pipe(concatMap((x,i) => foo(x.userId,i)))),
  )
  .subscribe()
   
<script src = "https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.6.2/rxjs.umd.min.js"></script>

Насколько мне известно, оператор groupBy ожидает, что userEvent$ observable завершится до того, как он начнет испускать какие-либо элементы. Таким образом, это решение не будет работать в режиме реального времени (когда userEvent$ не завершится).

dps 27.12.2020 14:57

что заставляет вас думать так? попробуй userEvent$ = timer(0,1000).pipe(map(x => ({userId:x})))

Rafi Henig 27.12.2020 15:29

Другие вопросы по теме