I have a service with a subject:
@Injectable() export class UserService() {
private currentUserSubject = new BehaviorSubject<User>(null);
public currentUser = this.currentUserSubject.asObservable().distinctUntilChanged();
... // emitting new User
}
Have a component I inject this service into and subscribing on updates:
@Component() export class UserComponent {
constructor(private userService: UserService) {
this.userService.currentUser
.subscribe((user) => {
// I want to see not null value here
})
}
}
I want to apply something to Observable<User>
to filter all null values and get into subscribe only when User
is actually loaded.
Add a filter operator to your observable chain. You can filter nulls explicitly or just check that your user is truthy - you will have to make that call depending on your needs.
Filtering out null users only:
public currentUser = this.currentUserSubject
.asObservable()
.filter(user => user !== null)
.distinctUntilChanged();
Another way to check the value exists:
public currentUser = this.currentUserSubject
.asObservable()
.filter<User>(Boolean)
.distinctUntilChanged();
with rxjs@6
and typescript the recommended (readable/maintainable) way is to define the following type guard:
export function isNonNull<T>(value: T): value is NonNullable<T> {
return value != null;
}
and augment a subject with pipe
and filter
:
subject.pipe(filter(isNonNull))
filter(user => !!user),
So would filter these falsy values (link to Falsy on MDN). or alternatively cast to a boolean like this:
filter(user => Boolean(user)),
If user evaluates to false, the filter will not be passed.
If you want to add some more proper typescript solution you could use a type predicate (user-defined type guard). See documentation on this here on https://www.typescriptlang.org/ .
Assume you have a class User
.
Example:
const isUser = (user: null|User): user is User => {
// Using an instance of check here, which is not the most performant
// but semantically most correct.
// But you could do an alternative check and return a boolean instead
return user instanceof User;
}
If you now do:
filter(user => isUser(user));
Typescript will understand that you have an object of type User
after the filter.
Another option for rxjs@6 is to create another wrapping operator of skipWhile
.
// rxjs.utils.js
export const skipNull = () => <T>(source: Observable <T>): Observable<T> => source.pipe(skipWhile(value => value === null));
Usage:
this.observable.pipe(skipNull()).subscribe(...)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With