也许这真的太复杂了,也许值得一看。
这个想法是有 2 个不同的 observables,创建转换源observable$
然后最终合并。
第一个 Observable,我们称之为obsFilterAndMapped
,是您进行过滤和映射的地方。
第二个 Observable,让我们称之为它,是一个 Observable,它在第一个 Observable (即,发出)的任何时候obsTapDelay
以一定的延迟触发一个新的计时器——一旦传递了延迟时间,那么你就执行你的操作——如果第一个 Observable 在之前发出一个新值延迟时间已过,然后创建一个新计时器。obsFilterAndMapped
tapAfterTime
这是实现这个想法的代码
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
全局变量隐藏在闭包中,但这会增加代码的复杂性,并且可能不值得。