为什么在模板中的异步管道正确刷新时未触发可观察的subscription()?

时间:2018-07-14 11:24:28

标签: angular observable

使用setAdminLogicalUser()以编程方式将服务类的可观察值设置为新值时,模板值会正确刷新,而不会执行组件类中的观察代码。

我认为不执行观察代码的原因是由于以下简单的事实:将可观察对象设置为新实例,因此任何观察者都将“丢失”而替换了旧实例。但是,为什么模板仍然可以刷新,它在内部是否使用另一种订阅观察者的方式?

服务:

    @Injectable()
    export class AuthService {

      user: Observable<User>;

      constructor(
        private afAuth: AngularFireAuth,
        private afs: AngularFirestore) {

        this.user = this.afAuth.authState
          .switchMap(user => {
            if (user) {
              return this.afs.doc<User>(`users/${user.uid}`).valueChanges()
            } else {
              return Observable.of(null)
            }
       })

       setAdminLogicalUser(uid: string) {
         this.user = this.afs.doc<User>(`users/${uid}`).valueChanges()
       }
    }

组件模板:

  <div *ngIf="auth.user | async as user">
    <!-- following attributes properly refresh after authService.setAdminLogicalUser() -->
    <h1 *ngIf="!auth.isAdmin(user)">{{user.firstName}} {{user.lastName}}</h1>
    ...

组件类:

export class ProfileComponent {
  constructor(
    public auth: AuthService
  }

  ngOnInit() {
    this.auth.user.subscribe(userData => {
      // not executed after authService.setAdminLogicalUser()
      console.log('this.auth.user.subscribe')
    })
  }
}

1 个答案:

答案 0 :(得分:1)

因为Angular使用更改检测,因此在每次更改检测时都会评估模板中的表达式。

因此,它检测到auth.user已更改,并将新值传递到async管道。

ngOnInit中的代码仅执行一次,因此订阅了user执行时存储在auth中的ngOnInit观察值。

不要为可观察对象分配新值,而应从不更改可观察对象,而应该从该可观察对象发出新值(即使用Subject)。