Может быть, это действительно слишком сложно, может быть, это стоит посмотреть.
Идея состоит в том, чтобы иметь 2 различные наблюдаемые, созданные для преобразования источника observable$
и затем в конечном итоге объединить.
first Observable, назовем его obsFilterAndMapped
, это тот, где вы выполняете фильтрацию и отображение.
Второй Observable, назовем его obsTapDelay
, это Observable, который запускает новый таймер с определенным задержка в любое время, когда первая Наблюдаемая, т.е. obsFilterAndMapped
, испускает - после того, как delayTime пройден, вы выполняете действие tapAfterTime
- если первая Наблюдаемая испускает новое значение перед delayTime передается, затем создается новый таймер.
Этот код реализует эту идею
const stop = new Subject<any>();
const obsShared = observable$.pipe(
finalize(() => {
console.log('STOP');
stop.next();
stop.complete()
}),
share()
);
const delayTime = 300;
const tapAfterTime = (value) => {
console.log('tap with delay', value)
};
let valueEmitted;
const obsFilterAndMapped = obsShared.pipe(
tap(val => valueEmitted = val),
filter(i => i > 7),
map(val => val + ' mapped')
);
const startTimer = merge(of('START'), obsFilterAndMapped);
const obsTapDelay = startTimer.pipe(
switchMap(val => timer(delayTime).pipe(
tap(() => tapAfterTime(valueEmitted)),
switchMap(() => empty()),
)),
takeUntil(stop),
)
merge(obsFilterAndMapped, obsTapDelay)
.subscribe(console.log, null, () => console.log('completed'))
При таком подходе вы выполняете действие tapAfterTime
в любое время источник observable$
не излучает ничего дольше delayTime
.Другими словами, это будет работать не только для первой эмиссии observable$
, но и для всей ее жизни.
Вы можете протестировать такой код с помощью следующего ввода
const obs1 = interval(100).pipe(
take(10),
);
const obs2 = timer(2000, 100).pipe(
take(10),
map(val => val + 200),
);
const observable$ = merge(obs1, obs2);
Еще немного поработавмы можем даже подумать, чтобы скрыть глобальную переменную valueEmitted
внутри замыкания, но это увеличило бы сложность кода и, вероятно, не стоило.