Проверьте этот интерактивный стек и этот статический пример, а именно
Основной трюк состоял в том, чтобы подождать хотя бы
- уведомление показывает задержку
- и следующее сообщение в потоке
и позволяет входам и выходам мыши увеличивать задержку.
Магия внутриconcatMap
делает это (по крайней мере, я так думаю ...)
Чтобы начать , мы берем notifications$
и concatMap с задержкой.Поэтому каждое сообщение будет отображаться как минимум DELAY
время
ПРИМЕЧАНИЕ: псевдокод
notifications$.concatMap(msg =>
timer(DELAY)
.ignoreElements()
.startWith(msg)
)
Затем мы хотим, чтобы мышь задерживалазадержка
notifications$
.concatMap(msg =>
mouse$
.switchMap(isOver => { // < We re-delay on mouse state change
if (isOver) {
return empty() // < Do nothing when user hovers
}
return timer(DELAY); // < after DELAY -- take in next msgs
})
// we need only one completion event from this mouse$+ stream
.take(1)
// existing logic to turn delay stream into msg stream with delay
.ignoreElements()
.startWith(msg)
)
Наконец , если следующее сообщение приходит после ЗАДЕРЖКИ - нам все равно нужно прослушивать зависания мыши и задерживать их
// store current msg index
let currentMsgIndex = -1;
notifications$
// store current msg index
.map((msg,i) => {
currentMsgIndex = i;
return msg;
})
.concatMap((msg, i) => {
// we listen to events from the mouse
return memMouse$
// if mouse pos changed -- reeval timeout
.switchMap(value => {
// do nothing on mouse in
if (value) {
return empty();
}
// until next msg comes in -- we're tracking mouse in/out
let nextMsgAwait$;
if (i == currentMsgIndex) {
// current msg is latest
nextMsgAwait$ = notifications$.pipe(take(1));
} else {
// we already have next msgs to show
nextMsgAwait$ = of(void 0);
}
// if mouse is away -- wait for
// - timer for TIMEOUT
// - and till new msg arrives
// until then -- user can mouse in/out
// to delay the next msg display
return forkJoin(
timer(TIMEOUT)
, nextMsgAwait$
);
}),
// we need only one completion event from this mouse$+ stream
.take(1)
// existing logic to turn delay stream into msg stream with delay
.ignoreElements()
.startWith(msg)
})
Для лучшегопонимание, пожалуйста, смотрите вышеупомянутые примеры - я добавил туда несколько комментариев.