RxJS delay at least X milliseconds
Based on Bogdan Savluk answer. Delay functionality decoupled:
let effectiveDelay=(delay)=>{
let effectiveTimer = (now=>delay=>timer(delay+now - Date.now() )) (Date.now())
return delayWhen(()=>effectiveTimer(delay));
}
this.eventThatFires
.switchMap(data => this.callHttpService(data)
.pipe(effectiveDelay(500)))
Case of http request (poll at least every x seconds)
of({}).pipe(
switchMap(data => {
return ajax({url:"https://httpbin.org/delay/2", crossDomain:true})
.pipe(effectiveDelay(1000), map(ax=>ax.response) )
}), tap(display), repeat())
.subscribe()
See: online
Effectively delay
by date is the same as delay
by number, the only difference is that delay duration is computed as difference of specified date and current time.
You can use delayWhen
operator to compute delay when value is emitted:
this.eventThatFires
.switchMap(data => {
let startTime = Date.now();
return this.callHttpService(data)
.delayWhen(() => Rx.Observable.timer(500 + startTime - Date.now()))
})
What is wrong with your combineLatest solution?
You can also use zip
:
this.eventThatFires
.switchMap(data => Observable.zip(
this.profileService.updateInfo(profileInfo)),
Observable.timer(500),
x => x));
I made a custom rxjs operator based off of Martin's final solution.
import { combineLatest, Observable, OperatorFunction, timer } from "rxjs";
import { map } from "rxjs/operators";
export function delayAtLeast<T>(delay: number): OperatorFunction<T, T> {
return function(source$: Observable<T>): Observable<T> {
return combineLatest([timer(delay), source$]).pipe(map(x => x[1]));
}
}