基于@PhiLho 的answer https://stackoverflow.com/a/35491598/3182091,我写了一个可管道操作符,它正是这样做的:
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
.
然后它开始一个timer
,使用给定的delay
.
如果这个定时器发出一个next
-事件,调用该函数。
但是,如果源发出next
, the timer
被取消并开始新的。
In the complete
的源头,timer
终于被取消了。
然后可以像这样使用该运算符:
this.loadResults().pipe(
executeDelayed(
() => this.startLoading(),
500
)
).subscribe(results => this.showResult())
我自己并没有编写很多运算符,因此这个运算符实现可能不是最好的,但它确实有效。
欢迎任何有关如何优化它的建议:)
EDIT:正如 @DauleDK 提到的,在这种情况下,错误不会停止计时器,并且fn
将在之后调用delay
。如果这不是你想要的,你需要添加一个onError
- 回调中tap
,这称为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()
)
);
}
}