【问题标题】:How to use an observable in angular 2 guards' canActivate()如何在 Angular 2 守卫的 canActivate() 中使用 observable
【发布时间】:2016-09-02 10:30:42
【问题描述】:

我为我的 angular2 rc5 应用程序创建了一个身份验证保护。

我也在使用 redux 商店。在该商店中,我保留了用户的身份验证状态。

我读到守卫可以返回一个可观察或承诺 (https://angular.io/docs/ts/latest/guide/router.html#!#guards)

我似乎无法找到一种方法让守卫等到商店/可观察对象更新,并且只有 更新后才返回守卫,因为默认值商店的永远是假的。

第一次尝试:

@Injectable()
export class AuthGuard implements CanActivate {

  @select(['user', 'authenticated']) authenticated$: Observable<boolean>;

  constructor() {}

  canActivate(): Promise<boolean> {

    return new Promise((resolve, reject) => {

      // updated after a while ->
      this.authenticated$.subscribe((auth) => {

        // will only reach here after the first update of the store
        if (auth) { resolve(true); }

        // it will always reject because the default value
        // is always false and it takes time to update the store
        reject(false);

      });

    });

  }

}

第二次尝试:

@Injectable()
export class AuthGuard implements CanActivate {

  @select(['user', 'authenticated']) authenticated$: Observable<boolean>;

  constructor() {}

  canActivate(): Promise<boolean> {

    return new Promise((resolve, reject) => {

      // tried to convert it for single read since canActivate is called every time. So I actually don't want to subscribe here. 
      let auth = this.authenticated$.toPromise(); 

      auth.then((authenticated) => {

        if (authenticated) { resolve(true); }

        reject(false);

      });

      auth.catch((err) => {
        console.log(err);
      });

  }

}

【问题讨论】:

标签: javascript angular angular2-routing


【解决方案1】:

订阅observable时,可以提供回调函数;在下面的例子中,我称之为CompleteGetCompleteGet() 只会在成功获取返回数据而不是错误时调用。您可以在回调函数中放置您需要的任何后续逻辑。

getCursenByDateTest(){
 this.cursenService
   .getCursenValueByDateTest("2016-7-30","2016-7-31")
   .subscribe(p => {
     this.cursens = p;
     console.log(p)
     console.log(this.cursens.length);
   },
   error => this.error = error,
   () => this.CompleteGet());
}

completeGet() {
   // the rest of your logic here - only executes on obtaining result.
}

我相信你也可以将 .do() 添加到 observable 订阅中来完成同样的事情。

【讨论】:

  • 在我的第一个示例中,我使用了该回调。问题是商店将成功返回数据。但这是默认值。我想等待包含真实身份验证值的 store observable 的第一次更新。
  • 然后我会单独订阅可观察的商店,并在它返回值时继续。
【解决方案2】:

您需要做的就是强制更新 observable:

canActivate(): Observable<boolean> {
    return this.authenticated$.take(1);
}

编辑: canActivate 等待源 observable 完成,并且(很可能,我不知道幕后发生了什么)authenticated$ observable 发出 .next(),而不是 .complete()

来自文档:http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-take
.take(1) 方法获取源 observable 发出的第一个值,然后完成

编辑2: 我刚刚看了你粘贴的 sn-p,我是对的 - store.select() observable 永远不会完成,它总是发出 .next

【讨论】:

  • 它是否等待流进行所需的更新?
  • 是的,它不会发出任何东西,直到源 observable 发出我用更多解释编辑了我的答案
  • 据我了解,你不能一直跟踪 observable,在它发出第一个事件后,路由的访问权限将是永久的,即使 observable 稍后发出不同的值。这不适合我的用例。
【解决方案3】:

订阅不返回 Observable。 但是,您可以像这样使用地图运算符:

this.authenticated$.map(
    authenticated => {
        if(authenticated) {
            return true;
        } 
    return false;
    }
 ).first() // or .take(1) to complete on the first event emit

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-26
    • 2018-01-02
    • 2021-09-13
    • 2018-12-22
    • 2017-11-11
    • 2016-11-02
    • 1970-01-01
    • 2021-11-21
    相关资源
    最近更新 更多