RxJS Mastery – #64 delay & delayWhen

RxJS delay and delayWhen

The RxJS delay and delayWhen operators are part of the utility operators. The delay operator comes in two variants, either delaying for a few milliseconds or until a specific date. For delayWhen a second Observable determines the timespan.

RxJS delay by milliseconds

When the delay operator receives a number it simply delays for some milliseconds. In the below example, interval would start emitting 0 at time frame 1. But thanks to delay the emission is shifted to 2 time frames later.

const source$ = interval(1).pipe(
    take(4),
    delay(2),
);

expectObservable(source$).toBe(
    '---abc(d|)', { a: 0, b: 1, c: 2, d: 3 }
);

RxJS delay until a certain Date

The second delay variant is a bit more tricky as it lets you specify the date until the values should be delayed. In the below test, we are using the now and time method of the TestScheduler. This allows us to specify a Date 3 time frames from now.

const t = time('---|');
const delayedUntil = new Date(testScheduler.now() + t);

const source$ = cold('-a|').pipe(
    delay(delayedUntil)
);

expectObservable(source$).toBe(
    '---(a|)'
);

Importantly, the delay is not added up with the time frame (“-“) specified in front of the a in the cold Observable. If the emission would have happened before the Date that is passed to delay, the emission happens and no further delay is caused.

The RxJS delayWhen is controlled by another Observable

The delayWhen operator is like delay but the timespan is determined by a delayDurationSelector that returns another Observable. The delayDurationSelector receives the value as well as the index of the emission and can customize the waiting based on those. This would even allow to reorder values as shown in the following test:

const source$ = cold('-abc|').pipe(
    delayWhen((val: string, index: number) => {
       if (val === 'b') {
           return cold('----t');
       }
       return cold('-t');
    })
);

expectObservable(source$).toBe(
    '--a-c-(b|)'
);

The value b is delayed a little bit longer than the rest and therefore it even arrives after c in the final output.

Exercise for the RxJS delay operator 💪

Show in a test what happens if you set the Date for the delay operator to a Date in the past. Are any values emitted?

const source$ = cold('-a|').pipe(
    delay(delayedUntil)
);

This post is part of the RxJS mastery series. As always the code examples can be found on GitHub.