RxJS Mastery – #53 combineLatestAll

RxJS combineLatestAll

The RxJS combineLatestAll flattens an Observable of Observables by applying combineLatest.

RxJS combineLatestAll flattens

Remember that combineLatest waits until every Observable has emitted at least once before combining the values. Let’s start with an example and explain based on that what functionality is behind combineLatestAll:

const source$ = interval(1000).pipe(take(2));

const result$ = source$.pipe(
    map(outer =>
        interval(1000).pipe(
            map(inner => `${outer} and ${inner}`),
            take(2)
        )
    )
);

result$
    .pipe(combineLatestAll())
    .subscribe(console.log)

The above example will produce the following output:

[ '0 and 0', '1 and 0' ]
[ '0 and 1', '1 and 0' ]
[ '0 and 1', '1 and 1' ]

Generally

  • every time an inner Observable emits, the combineLatestAll is emitting
  • an array of the most recent values is emitted

This sounds a bit abstract. So, let’s construct a more concrete example in the next section.

Two Inner Observable for two different source values

Imagine we have a source stream of numeric IDs (1, 2). For each ID two responses are retrieved and the goal is to flatten everything and deliver always the current values for both (as soon as both have emitted at least once).

const source$ = cold('-1-2-|', {'1': 1, '2': 2});
const b: (id: number) => Observable<string> = (id: number) => {
    return cold('-ij', {
        i: `1st response ID ${id}`,
        j: `2nd response ID ${id}`,
    });
};

const result$ = source$.pipe(
    map(o => b(o)),
    combineLatestAll(),
);

This will end up in the following output:

// [ '1st response ID 1', '1st response ID 2' ]
// [ '2nd response ID 1', '1st response ID 2' ]
// [ '2nd response ID 1', '2nd response ID 2' ]

As you can see the first emission of the current response state for both IDs happens as soon as the ID 2 also has got its first response. Hence, the output is ['1st response ID 1', '1st response ID 2']. From now on the emission happens as soon as new values arrive for either of the source values. Therefore the second emission contains already the updated value for ID 1, while ID 2 is still on the first response. Finally, the output is ['2nd response ID 1', '2nd response ID 2'], representing the final state.

Exercise for the RxJS combineLatestAll operator 💪

Use interval and combineLatestAll to output the following structure:

[ 0, 0, 0 ]
[ 1, 0, 0 ]
[ 1, 1, 0 ]
[ 1, 1, 1 ]
[ 2, 1, 1 ]
[ 2, 2, 1 ]
[ 2, 2, 2 ]

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