I have this RxJS stream defined in a class that is giving me trouble:
export class Auth {
// ...
#login$ = new Subject<Credentials>();
#logout$ = new Subject<void>();
#storageToken = of(this.#localStorage.token);
#loginToken$ = this.#login$.pipe(switchMap((credentials) => getToken(credentials)));
#token$ = this.#storageToken.pipe(
concatWith(merge(this.#loginToken$, this.#logoutToken$)),
);
user$ = this.#token$.pipe(
switchMap((token) => (token === null ? of(null) : this.#accountService.getUser())),
catchError(() => this.#handleError()),
distinctUntilChanged(),
tap((user) => console.log('User:', user)),
);
login(credentials: Credentials): void {
this.#login$.next(credentials);
}
logout(): void {
this.#logout$.next();
}
}
The class only exposes access to user$
stream and login/logout functions. My idea is that, when my app starts, if there’s a token in the browser storage, then retrieve the user info using the token and emit it, otherwise emit null. This way, the app will always have the user data available if the token was stored, otherwise, will require the user to login.
The problem that I’m having is related to the #storageToken stream: whenever there’s a subscription to the user$ stream, #storageToken emits again, and I’d like it to emit just in the first subscription. I’ve tried replacing the concatWith with startWith, using a Behavior subject, and other options, but I cannot find the way to achieve my goal.