【问题标题】:Angular 6 Route Guard Shows White PageAngular 6 Route Guard 显示白页
【发布时间】:2019-01-22 11:44:06
【问题描述】:

我正在尝试添加一个 Route Guard,它将向 PHP API 发送 JWT,该 API 将根据用户是否通过身份验证返回 true 或 false。通过我的测试,Route Guard 一直有效,直到它真正调用 API。如果 API 返回 false,则守卫按预期工作。但是,如果 API 返回 true,那么守卫似乎想要重定向用户,就好像它返回 false 一样,但它没有显示主屏幕,而是只显示一个空。

auth.guard.ts

canActivate(): boolean {
    if (localStorage.getItem('portfolioJWT') === null) {
        this.router.navigate(['/']);
        return false;
    } else {
        const token = JSON.parse(localStorage.getItem('portfolioJWT'));

        this.authService.isAuth(token).subscribe(res => {
            console.log(res);
            if(!res) {
                this.router.navigate(['/']);
                console.log("NOT Authorized");
                return false;
            } else {
                console.log("Authorized");
                return true;
            }
        });
    }
}

auth.service.ts

isAuth(token: string): Observable<Boolean> {

  const authHttpOptions = {
      headers: new HttpHeaders({
          'Content-Type': 'application/x-www-form-urlencoded',
          'Authorization': 'Bearer ' + token
      })
  };

  return this.http.post<Boolean>('http://portfolioapi/api/checkAuth', {}, authHttpOptions);
}

我让守卫控制台记录返回的值,以及用户是否被授权,它会显示正确的数据。

【问题讨论】:

  • 尝试路由到不同的路由,而不是正斜杠。看看行不行?
  • 所以console.log(res) 会在授权情况下返回true

标签: angular angular-router angular-route-guards


【解决方案1】:

问题可能是您没有为 canActivate 使用Promise&lt;boolean&gt;,所以当 canActivate 仍在后台执行时, 路由器已经移动,因此触发了意外行为。

一个例子可能是 API 返回false 并初始化一个navigate,但只有在路由器已经导航你到某个地方之后(这可能会触发空白页面)。 console.log(res) 也是如此。它可能工作,但已经太晚了,路由器已经移动了。

您想要实现的是路由应该暂停,直到收到true 或false。在没有 Promise 的情况下检查局部变量的值可能会正常工作,但在执行 API 调用时确实很重要,因为它是异步,所以你明确需要告诉路由器等待通话结束。

canActivate(): Promise<boolean> {
    return new Promise((resolve) => {
        if (localStorage.getItem('portfolioJWT') === null) {
            this.router.navigate(['/']);
            resolve(false);
        } else {
            const token = JSON.parse(localStorage.getItem('portfolioJWT'));

            this.authService.isAuth(token).subscribe(res => {
                console.log(res);
                if(!res) {
                    this.router.navigate(['/']);
                    console.log("NOT Authorized");
                    resolve(false)
                } else {
                    console.log("Authorized");
                    resolve(true)
                }
            });
        }
    })
}

【讨论】:

  • 你不需要承诺。守卫可以(并且经常这样做)返回真或假。实际上,建议您不要在 Angular 中使用 Promise,除非绝对需要与需要它们的外部 API 进行通信。此外,使用HttpClient 时,您无需取消订阅。
  • @DeborahK 既然这是 OP 问题的解决方案,那么如果没有 Promise,你将如何解决这个问题?当然 Guard 应该在这里返回 true 或 false,但是你需要 Promise 告诉路由器等待 API 调用(异步),对吗?关于订阅,我刚刚阅读了关于 HttpClient 和 Router 的那部分文档,你是对的,它们是自动清理的。答案已编辑。
  • Observables 是异步操作 Promise 的推荐替代方案。
猜你喜欢
  • 1970-01-01
  • 2017-04-22
  • 2017-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-16
  • 2019-01-19
  • 2018-03-18
相关资源
最近更新 更多