Если я правильно понял вашу проблему, я бы немного изменил мраморные диаграммы , которые вы предложили для вашей проблемы.
В частности, я бы изменил последнюю DCA
последовательность navNotifications
на CDA
, чтобы отразить тот факт, что в последовательности navCmds
сначала вы отправляете C
, а затем D
,Это означает, что мраморные диаграммы будут выглядеть следующим образом
navCmds --A----B---C--A------D-----------------C-----D----E--->
navNotifications ----A----X---B-C-A---D------------------------CDA---E->
result ---------X--------------------------------------A----->
Предполагая, что это правильно, что должно быть подтверждено, вы можете рассмотреть решение по этим направлениям
const queue = new Array<any>();
navCmds$.pipe(
tap(cmd => queue.push(cmd)),
switchMap(() => {
return navNotifications$.pipe(
switchMap(notification => {
const cmdFromQueue = queue[0];
if (notification === cmdFromQueue) {
queue.shift();
return empty();
} else {
return of(notification);
}
})
)
})
)
Идея здесь заключается в том, чтобы сначала
- создать
queue
, в котором вы сохраняете отправленные команды - каждый раз, когда
navCmds$
отправляет новую команду, значение равнонажмите queue
и поток переключится на navNotifications$
, который проверяет queue
и выдает notification
, если он отличается от последней обработанной команды
Это решение требует состояние должно поддерживаться с помощью переменной queue
, но это можно скрыть с помощью пользовательских конвейерных операторов.
Эти решения были протестированы со следующими тестовыми данными
const navCmds$ = new Subject<any>();
setTimeout(() => {navCmds$.next('A')}, 30);
setTimeout(() => {navCmds$.next('B')}, 80);
setTimeout(() => {navCmds$.next('C')}, 120);
setTimeout(() => {navCmds$.next('A')}, 150);
setTimeout(() => {navCmds$.next('D')}, 220);
setTimeout(() => {navCmds$.next('C1')}, 320);
setTimeout(() => {navCmds$.next('D1')}, 380);
setTimeout(() => {navCmds$.next('E')}, 430);
const navNotifications$ = new Subject<any>();
setTimeout(() => {navNotifications$.next('A')}, 50);
setTimeout(() => {navNotifications$.next('X1')}, 100);
setTimeout(() => {navNotifications$.next('X2')}, 110);
setTimeout(() => {navNotifications$.next('B')}, 130);
setTimeout(() => {navNotifications$.next('Y1')}, 140);
setTimeout(() => {navNotifications$.next('Y2')}, 150);
setTimeout(() => {navNotifications$.next('C')}, 160);
setTimeout(() => {navNotifications$.next('A')}, 180);
setTimeout(() => {navNotifications$.next('D')}, 230); // slightly delayed
setTimeout(() => {navNotifications$.next('C1')}, 390); // inverted
setTimeout(() => {navNotifications$.next('D1')}, 400); // inverted
setTimeout(() => {navNotifications$.next('A1')}, 410);
setTimeout(() => {navNotifications$.next('A2')}, 420);
setTimeout(() => {navNotifications$.next('A3')}, 440);
setTimeout(() => {navNotifications$.next('E')}, 460);