首页 > 解决方案 > Angular 中的 Meteor User Observable 没有按预期做出反应

问题描述

我目前正在通过meteor-rxjs包将 Meteor 与 Ionic 一起使用。最近我为登录工具栏制作了一个组件。如果我已登录,它应该显示我的用户名和头像,如果我当前未登录,它应该显示一个登录按钮。

该组件与一个帐户服务连接,该服务存储一个包含用户信息的 user$ Observable,因此它应该在我的登录状态发生变化时做出反应。

但是它并没有像预期的那样做出反应。如果我退出并尝试登录,则视图不会改变。但是,如果我在登录时重新加载页面,我可以注销并登录,并且视图总是会对我的状态变化做出反应。

账户服务:

export class AccountService {

  user$: Observable<Meteor.User>;

  constructor() {

    this.user$ = Users.find({_id: Meteor.userId()}).pipe(zoneOperator());

  }
}

注意: zoneOperator() 是来自 meteor-rxjs 的函数,每次新数据到达 Mongo 游标 observable 时都会调用 ngZone。

零件

  <ion-toolbar>
    <ion-buttons *ngIf="(account.user$ | async) as users" slot="end">

      <ion-item *ngIf="users.length > 0 ; else loginTP">
        <ion-avatar class="ion-margin-end">
          <img src="{{users[0].avatar}}">
        </ion-avatar>
        <ion-label>{{users[0].username}}</ion-label>

        <ion-button (click)="logout()">
          <ion-icon name="log-out-outline"></ion-icon>
        </ion-button>
      </ion-item>

      <ng-template #loginTP>
        <ion-button (click)="login()">
          <ion-icon slot="start" name="log-in-outline"></ion-icon>
          Login
        </ion-button>
      </ng-template>

    </ion-buttons>
  </ion-toolbar>

问题是如果我最初没有登录,视图不会更新。它仅在我一开始登录时才能按预期工作。我的假设是初始状态不是反应性的。

如果我没有登录,Meteor.userId() 为空。

但是在 AccountService 中记录 this.user$ 表明它Users.find({_id: null})仍然返回一个 Observable。

任何帮助,将不胜感激。:)

标签: angularmeteorrxjsobservable

解决方案


我找到了一个使用内置依赖跟踪系统的 Meteors 的解决方案:Tracker即使我最初已注销,它也会正确更新视图。这是最终代码:

服务

export class AccountService {

  user$: Observable<Meteor.User>;

  constructor() {
    const ctrl = this;

    Tracker.autorun(() => {
      Users.find({_id: Meteor.userId()})
          .pipe(take(1), zoneOperator())
          .subscribe(user => {
        if (user) {
          ctrl.user$ = user[0];
        } else {
          ctrl.user$ = EMPTY;
        }
      });
    });
  }

}

零件

  <ion-toolbar>
    <ion-buttons slot="end">
      <ion-item *ngIf="account.user$ as user ; else loginTP">
        <ion-avatar class="ion-margin-end">
          <img src="{{user.avatar}}">
        </ion-avatar>
        <ion-label>{{user.username}}</ion-label>

        <ion-button (click)="logout()">
          <ion-icon name="log-out-outline"></ion-icon>
        </ion-button>
      </ion-item>

      <ng-template #loginTP>
        <ion-button (click)="login()">
          <ion-icon slot="start" name="log-in-outline"></ion-icon>
          Login
        </ion-button>
      </ng-template>

    </ion-buttons>
  </ion-toolbar>

推荐阅读