Reputation: 10768
In the RxJs doc of combineLatest
, there is written:
Be aware that combineLatest will not emit an initial value until each observable emits at least one value.
Is there an operator that works like combineLatest
but that emit a value even if only one of the observable emits a value ?
Upvotes: 3
Views: 2747
Reputation: 8032
Assuming observables
is an array of observables
combineLatest(...observables.map(
s => s.pipe(
startWith(null)
)
)).pipe(
filter(arr => arr.filter(x => x != null).length > 0)
)
This will emit an array with null in any position where the source observable hasn't emitted yet. It also filters out the very first emission where the entire array is null.
The same thing, but perhaps a bit more robust as it allows for a dummy value with a shape that the developer knows.
You can replace 'null' with anything. For example:
combineLatest(...observables.map(
s => s.pipe(
startWith({dummy: true})
)
)).pipe(
filter(arr => arr.filter(x => !x?.dummy).length > 0)
)
At scale, looping through an array to see if all values are void/dummy values is bad for performance. Since (in this case) we only want to ignore the first emission, this custom operator can do that without checking the values at all.
filterFirst(n)
will ignore the first n
emmissions:
function filterFirst<T>(n: number): MonoTypeOperatorFunction<T>{
return s => defer(() => {
let count = 0;
return s.pipe(
filter(_ => n <= count++)
)
});
}
Then you can use it as follows:
combineLatest(...observables.map(
s => s.pipe(
startWith(null)
)
)).pipe(
filterFirst(1)
)
Upvotes: 4