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]));
  }
}