基于@PhiLho 的answer,我编写了一个可管道操作符,它正是这样做的:
export function executeDelayed<T>(
fn : () => void,
delay : number,
thisArg? : any
) : OperatorFunction<T, T> {
return function executeDelayedOperation(source : Observable<T>) : Observable<T> {
let timerSub = timer(delay).subscribe(() => fn());
return source.pipe(
tap(
() => {
timerSub.unsubscribe();
timerSub = timer(delay).subscribe(() => fn());
},
undefined,
() => {
timerSub.unsubscribe();
}
)
);
}
}
基本上它返回一个函数,该函数获取Observable source。
然后它使用给定的delay 启动一个timer。
如果此计时器发出next-事件,则调用该函数。
但是,如果源发出 next,则 timer 将被取消并开始一个新的。
在源的complete中,timer终于被取消了。
然后可以像这样使用此运算符:
this.loadResults().pipe(
executeDelayed(
() => this.startLoading(),
500
)
).subscribe(results => this.showResult())
我自己并没有编写很多运算符,所以这种运算符实现可能不是最好的,但它确实有效。
欢迎任何关于如何优化它的建议:)
编辑:
正如@DauleDK 提到的,在这种情况下,错误不会停止计时器,fn 将在delay 之后调用。如果这不是你想要的,你需要在tap中添加一个onError-callback,它调用timerSub.unsubscribe():
export function executeDelayed<T>(
fn : () => void,
delay : number,
thisArg? : any
) : OperatorFunction<T, T> {
return function executeDelayedOperation(source : Observable<T>) : Observable<T> {
let timerSub = timer(delay).subscribe(() => fn());
return source.pipe(
tap(
() => {
timerSub.unsubscribe();
timerSub = timer(delay).subscribe(() => fn());
},
() => timerSub.unsubscribe(), // unsubscribe on error
() => timerSub.unsubscribe()
)
);
}
}