I'm trying to implement the following behavior in RxJS:
This would is very useful for UX, because even if the call takes 1ms, I'd like to show a loading icon for at least 100ms.
I haven't found any way to implement this either with delay
, throttle
, debounce
or its variations.
this.eventThatFires
.switchMap(data => {
let startTime = Date.now();
return this.callHttpService(data)
.delay(new Date(startTime + 1000));
})
I assumed something like this worked, but using an absolute date seems to do a time difference with the current time, and not schedule the delay for that absolute time.
EDIT:
It seems there's no built-in operator that works as what I describe. I just created it because I'll be using it a lot throughout my application:
import { Observable } from "rxjs/Observable";
function delayAtLeast<T>(this: Observable<T>, delay: number): Observable<T> {
return Observable.combineLatest(
Observable.timer(delay),
this)
.map(([_, i]) => i);
}
Observable.prototype.delayAtLeast = delayAtLeast;
declare module "rxjs/Observable" {
interface Observable<T> {
delayAtLeast: typeof delayAtLeast;
}
}
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]));
}
}
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));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With