How to do something in Rx subscription only after valid value?
For example, I receive 'null', 'null' and only after this array with data
For example:
this.someStream$.subscribe((data: any[]) => {
if (data) {
this.someVar= data.map(item => new SomeModel(item ));
});
How to avoid "if (data) {}
"
As suggested, the filter
pipe does the job, but you explicitely don't want to have a conditional, which can be understood from a verbosity perspective. This is not very pretty, right?
filter(data => data !== undefined)
filter(data => !!data)
There are two solutions to avoid the !==
or the shorthand !!data
.
First, you can make use of the Boolean
constructor. It is a function with signature (any) => boolean
, that's why you can do this:
filter(Boolean)
Be careful though, als falsy values (false, "", 0) will also be filtered that way. It's only save to use with object
.
Even better and more reusable is creating an own operator, that would look like this:
function filterEmpty<T>(): MonoTypeOperatorFunction<T> {
return (source: Observable<T>) => source.pipe(filter(val => val != undefined));
}
Then, you can use it with your code example:
this.someStream$
.pipe(filterEmpty())
.subscribe((data: any[]) => {
this.someVar = data.map(item => new SomeModel(item ));
});
TYPES
There is another concern with this approach, and that is types.
Imagine this:
class X {
public a;
}
let x: X | undefined = undefined;
of(x)
.pipe(filter(y => !!y))
.subscribe(y => {
let i = y.a;
});
We will get a type error when assigning i
, as y
is X | undefined
. Very unfortunate.
But with this typed operator, we can convert X | undefined
into X
:
export function filterNullable<T>(): OperatorFunction<T | undefined, T> {
return (source: Observable<T | undefined>) => source.pipe(
filter<T | undefined, T>(
function (val: T | undefined): val is T {
return val !== undefined;
}));
}
Very handy.