RxJS Mastery – #70 Conditional and Boolean Operators

RxJS conditional and boolean operators

RxJS offers a variety of conditional and boolean operators. Let us have a look at defaultIfEmpty, every, find, findIndex, and isEmpty.

RxJS defaultIfEmpty for default values

Observables wrap asynchronous operations that might not be 100% reliable. This means they sometimes either do not deliver a value or do not return it in time. In the best case, it is just a missing value, in the worst the Observables chain requires a value or would through an error otherwise. That is where defaultIfEmpty comes to the rescue.
If the Observable completes without emitting any next value, defaultIfEmpty delivers a specified value.

const result$ = cold('---|').pipe(
    defaultIfEmpty(0)
);

expectObservable(result$).toBe(
    '---(d|)',
    {
        d: 0,
    }
);

Of course, the default value can only be delivered on the 4th time frame when the original Observable has completed.

RxJS every to check the whole sequence

The RxJS every operator checks all the values that are emitted. If one value violates the condition specified, false is emitted and the Observable completes. If all values pass, true is emitted with completing.

const result$ = cold<number>('24678|').pipe(
    every(v => v % 2 === 0)
);

expectObservable(result$).toBe(
    '---(f|)',
    {
        f: false,
    }
);

In the below example, all values return true for the condition:

const result$ = cold<number>('2468|').pipe(
    every(v => v % 2 === 0)
);

expectObservable(result$).toBe(
    '----(t|)',
    {
        t: true,
    }
);

RxJS find to emit a single value matching a condition

Find checks every value in the stream and emits the first one for which the specified condition is true. At the same time, it sends a complete notification. The condition in the below example is checking for multiples of 3. In the sequence of numbers from 1 to 9, the first value that fulfills the condition is 3. Hence, 3 is emitted and the stream completes.

const result$ = cold<number>('123456789|').pipe(
    find(v => v % 3 === 0)
);

expectObservable(result$).toBe(
    '--(v|)', { v: "3" }
);

If no value fulfills the condition and the source completes, undefined is emitted. In the below test, we are trying to find an even number in a sequence of odd numbers:

const result$ = cold<number>('1357|').pipe(
    find(v => v % 2 === 0)
);

expectObservable(result$).toBe(
    '----(u|)', { u: undefined }
);

RxJS findIndex for finding the index

The findIndex operator works like find, but emits only the index of the first found value. So, if we’re taking the above example of the previous section, the index 2 is emitted and not the value 3:

const result$ = cold<number>('123456789|').pipe(
    findIndex(v => v % 3 === 0)
);

expectObservable(result$).toBe(
    '--(i|)', { i: 2 }
);

Please note that the case where no value is found does not end up with undefined. The value -1 is emitted instead, following the logic of javascript’s findIndex.

const result$ = cold<number>('1357|').pipe(
    findIndex(v => v % 2 === 0)
);

expectObservable(result$).toBe(
    '----(i|)', { i: -1 }
);

RxJS isEmpty emits true if the source is not emitting any values

The final operator that we are looking into in the area of conditional and boolean operators, is the isEmpty operator. As the name suggests, it checks the source for any values. If no values are emitted by the source, the value true is emitted and the Observable completes.

const result$ = cold<number>('----|').pipe(
    isEmpty()
);

expectObservable(result$).toBe(
    '----(t|)', { t: true }
);

Once a value is found, the stream completes and emits false:

const result$ = cold<number>('---123|').pipe(
    isEmpty()
);

expectObservable(result$).toBe(
    '---(f|)', { f: false }
);

Exercise for the RxJS conditional and boolean operators 💪

Prevent the EmptyError in the below Observable chain. Deliver the value 0 instead.

const result$ = cold('---|').pipe(
    first(),
);

expectObservable(result$).toBe(
    '---(d|)',
    {
        d: 0,
    }
);

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