Angular 9 - 关于 observable 和 map() 的问题,它如何 return 一个 class 的特定 属性?

Angular 9 - Question about observable and map(), how does it return a specific property of a class?

我在继续一个前同事的项目,我对一些代码有疑问,我不明白其中的某些部分。

为了给您一些背景信息,我们有一个 UserInfo class,它看起来像:

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");
    }
  }
}

然后在 Service class 中,我们有 2 个 observables,用于属性 loginMethodsloginMethodsAvailable.

 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 || []));

现在第一个疑问是,在这两个可观察量中,我们 map() LoginInfo class,但是 "how" 是否分配了 class 属性 loginMethodsloginMethodsAvailable 到 对吗?我希望我的意思很清楚,从这段代码来看,这两个 observable 似乎是相同的,它们只是使用了不同的 behaviourSubject,但是如何 代码知道一个用于 class 属性 loginMethods,一个用于 loginMethodsAvailable? 最初我认为使用 map(),如果你使用 Class 属性 的确切名称,它将过滤那个可观察的并只输出那个 属性,但是使用的名称map() 在两种情况下都是相同的,所以没关系。

最后可能是关键部分,是这个 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 只是主要的可观察值:

  private readonly _userSub = new BehaviorSubject<UserInfo>(null);
  public readonly User = this._userSub.asObservable();

那么构造函数中发生了什么?我从未见过这种语法,订阅并传递给它 BehaviorSubject?

同样,我的主要疑问是,observable loginMethod 和 observable loginMethodAvailable 如何发出正确的值?这段代码的哪一部分定义了?

代码有效,当我订阅 loginMethod 时,输出值是 class UserInfo 的 属性 loginMethods: <LoginInfo[]>,当我订阅 loginMethodAvailable,我得到 属性 loginMethodsAvailable:<LoginInfo[]> 的值,我只是不明白如何。

希望我说清楚了!

So what is going on in the constructor? I never seen this syntax, subscribing and passing to it a BehaviorSubject?

当您有多个订阅者并期望他们中的每一个都收到相同的值时,您必须使用 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?

根据不同的情况,它们会发出不同的值。

查看带有代码示例的示例片段。

const _loginMethodSub = new rxjs.BehaviorSubject();
const _loginMethodAvailableSub = new rxjs.BehaviorSubject();
const _userSub = new rxjs.BehaviorSubject(null);
const User = _userSub.asObservable();

const loginMethod = _loginMethodSub.asObservable().pipe(
  rxjs.operators.map(loginMethod => loginMethod || []));

loginMethod.subscribe(value => {
  console.log(value);
})

const loginMethodAvailable = _loginMethodAvailableSub.asObservable().pipe(
  rxjs.operators.map(loginMethod => loginMethod || []));

loginMethodAvailable.subscribe(value => {
  console.log(value);
})

console.log('User.pipe call ctor')

User.pipe(rxjs.operators.map(uInfo => uInfo && uInfo.loginMethods)).subscribe(_loginMethodSub);

User.pipe(rxjs.operators.map(uInfo => uInfo && uInfo.loginMethodsAvailable)).subscribe(_loginMethodAvailableSub);

console.log('api call')

_userSub.next({
  loginMethods: [{
    loginID: 1,
    displayName: 'test1',
    logoUrl: 'test1'
  }, {
    loginID: 2,
    displayName: 'test2',
    logoUrl: 'test2'
  }],
  loginMethodsAvailable: [{
    loginID: 1,
    displayName: 'test1',
    logoUrl: 'test1'
  }]
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.js"></script>