typescript - RxJS fördröj minst X millisekunder


Jag försöker implementera följande beteende i RxJS:

  1. Utlös ett evenemang
  2. Anropa ett HTTP-API
  3. När API:et returnerar, antingen:

    1. Vänta tills minst X millisekunder har förflutit sedan händelsen utlösts
    2. Returnera omedelbart om X millisekunder redan har passerat sedan händelsen utlösts

Detta skulle vara mycket användbart för UX, eftersom även om anropet tar 1 ms vill jag visa en laddningsikon i minst 100 ms.

Jag har inte heller hittat något sätt att implementera detta med delay, throttle, debounce eller dess variationer.

this.eventThatFires
    .switchMap(data => {
        let startTime = Date.now();
        return this.callHttpService(data)
            .delay(new Date(startTime + 1000));
    })

Jag antog att något sådant fungerade, men att använda ett absolut datum verkar göra en tidsdifferens med den aktuella tiden, och inte schemalägga försening för den absoluta tiden.

REDIGERA :

Det verkar inte finnas någon inbyggd operator som fungerar som det jag beskriver. Jag skapade den precis eftersom jag kommer att använda den mycket i hela min applikation:

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

Svar #1

Effektivt är fördröjning efter datum samma som fördröjning efter nummer, den enda skillnaden är att fördröjningsperioden beräknas som skillnaden mellan det angivna datumet och aktuell tid.

Du kan använda delayWhen-operatorn för att beräkna fördröjning när ett värde emitteras:

this.eventThatFires
    .switchMap(data => {
        let startTime = Date.now();
        return this.callHttpService(data)
            .delayWhen(() => Rx.Observable.timer(500 + startTime - Date.now()))
    })

Svar #2

Vad är fel på din combineLatest-lösning?

Du kan också använda zip:

this.eventThatFires
    .switchMap(data => Observable.zip(
        this.profileService.updateInfo(profileInfo)),
        Observable.timer(500),
        x => x));

Relaterade artiklar