【问题标题】:Why does Angular 2's CanActivate return an Observable<boolean> instead of a Promise?为什么 Angular 2 的 CanActivate 返回 Observable<boolean> 而不是 Promise?
【发布时间】:2016-08-10 20:45:01
【问题描述】:

CanActivate class 允许 Observable&lt;boolean&gt; 返回类型。

对我来说唯一有意义的用例是:

  1. CanActivate 可以“异步”阻止正在显示的路线,直到调用 observer.next(true|false)
  2. 我可以显示CanActivate 允许的路线,然后从我的应用程序的另一部分推送observer.next(false) 并让该路线消失。

但是,第 1 点有效,但第 2 点无效。因此,除了方便之外,我找不到CanActivate 应该允许Observable&lt;boolean&gt; 的返回类型的原因——这反过来又使API 复杂化。如果CanActivate 只允许boolean 返回类型和Promise,那会更简洁。

请注意,我是 Angular、RxJS 和所有基于 Node 的新手,所以我可能会遗漏一些显而易见的东西。我花了一段时间试图从CanActivate 中提取Observer&lt;boolean&gt; 返回类型所暗示的功能。

【问题讨论】:

  • 他们决定不使用 Promises,用 Observables 代替它们。你当然可以拥有一个在完成之前只返回一个值的 Observable,例如,所有的 http 调用现在都是 Promise。
  • 为什么不问问那些构建了 v3 路由器所基于的路由器的开发人员呢? Create an issue,问这个问题,你可能会得到答案。
  • 好的就行。不确定这是不是一个愚蠢的问题。

标签: javascript angular rxjs rxjs5


【解决方案1】:

在 AngularJS 2 中,几乎每个异步操作都返回 Observable。因为您可以实现自己的 CanActivate,所以您可能希望通过服务器访问来实现。例如,检查服务器中的管理员凭据。你可以看到类似的例子here

如果此方法返回布尔数据类型,您需要阻止页面才能这样做。

【讨论】:

    【解决方案2】:

    它可以让你执行一些异步进程。想象一下,您有一个来自身份验证服务的 currentUser 可观察值。这是一个ReplaySubscriber(1);,并且总是返回当前登录的用户,但是当你的应用第一次加载时,auth 调用可能仍在处理中,所以你不知道它是否完整。

    CanActivate() {
      return this.currentUser.map(user => user && user.isActive());
    }
    

    【讨论】:

    • 使用Observable 意味着我也获得了我在问题第二点中描述的功能,因为它们是为推送multiple values 而设计的。 CanActivate 只能在取消订阅 observable 之前推送 one 值。因此,Promise 返回类型肯定更合适。我会更清楚地更新我的问题。
    • 我相信 CanActivate 仅在激活之前进行检查。我不相信它在路由被激活后一直在监听那个 observable。
    • 是的,这就是我看到的功能,这就是为什么我认为返回 Promise 会更合适。
    【解决方案3】:

    在 Angular 7 中,canActivate 可以返回 ObservablePromise 和简单的 booleanHTTP 调用也是如此,所以你可以返回任何适合你的类型,对我来说,我将它们都用作以下内容:

    如果是Observable

    public getCats(): Observable<Cat[]> {
    
        return this.http.get<Cat[]>(this.catsUrl, this.getHttpOptions()).pipe(
          tap(_ => this.log('fetched cats')),
          catchError(this.handleError())
        );
      }
    

    canActivate 的情况下,我使用Promise&lt;boolean&gt;HTTP 在以下情况下调用:

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
        const currentUser = this.getCurrentUser();
        if (currentUser) {
            return this.http.post<any>(this.validateUserUrl, this.userData).toPromise().then(
                response => 
                {
                    return true;
                }
            ).catch(
                error=>
                {
                    this.logout()
                    return false;
                }
            );
        }
        return new Promise<boolean>(()=> {return false;});
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多