I'm continuing the project of a former coworker, and I have a doubt on some code, I don't understand some parts of it.
To give you a little context, we have a UserInfo
class, and it looks like:
export class UserInfo {
constructor(
public readonly userLoginId: string,
public readonly hasLocalPassword: boolean,
public readonly loginMethods: Array<LoginInfo>,
public readonly loginMethodsAvailable: Array<LoginInfo>,
public readonly isAuthenticated: boolean,
) {}
}
export class LoginInfo {
constructor(
public readonly loginID: number,
public readonly displayName: string,
public readonly logoUrl: string
) {
if ([loginID, logoUrl, displayName].some(s => !s)) {
throw Error("not all arguments passed for LoginInfo");
}
}
}
then in a Service class
, we have 2 observables
, for the properties loginMethods
and loginMethodsAvailable
.
private readonly _loginMethodSub = new BehaviorSubject(Array<LoginInfo>());
private readonly _loginMethodAvailableSub = new BehaviorSubject(Array<LoginInfo>());
public readonly loginMethod = this._loginMethodSub.asObservable().pipe(map(loginMethod => loginMethod || []));
public readonly loginMethodAvailable = this._loginMethodAvailableSub.asObservable().pipe(map(loginMethod => loginMethod || []));
now the first doubt is, in both these observables, we map()
the LoginInfo
class, but "how" does it assign the class property loginMethods
or loginMethodsAvailable
to the
right observable? I hope it's clear what I mean, from this code, it seems that both observable are identical, they just use a different behaviourSubject
, but how does
the code know that one is for the class property loginMethods
, and one for loginMethodsAvailable
?
Initially I thought that with the map()
, if you use the exact name of the Class property, it will filter that observable and output only that property, but the names used in the map()
are identical in both cases so that doesn't matter.
finally what might be the key part, is the constructor of this Service
class:
constructor(private http: HttpClient) {
this.User.pipe(map(uInfo => uInfo && uInfo.loginMethods)).subscribe(this._loginMethodSub);
this.User.pipe(map(uInfo => uInfo && uInfo.loginMethodsAvailable)).subscribe(this._loginMethodAvailableSub);
}
this.User
is simply the main observable:
private readonly _userSub = new BehaviorSubject<UserInfo>(null);
public readonly User = this._userSub.asObservable();
So what is going on in the constructor? I never seen this syntax, subscribing and passing to it a BehaviorSubject
?
And again, my main doubt is, how does the observable loginMethod
and the observable loginMethodAvailable
, emit the right values? In what part of this code is that defined?
The code is working, when I subscribe to loginMethod
the output values are the Property loginMethods: <LoginInfo[]>
of the class UserInfo
, and when I subscribe to loginMethodAvailable
, I get the values of the property loginMethodsAvailable:<LoginInfo[]>
, I just don't understand how.
I hope I made myself clear!