【问题标题】:CanActivate guard leads to multiple http callsCanActivate 守卫导致多个http调用
【发布时间】:2021-09-13 16:11:24
【问题描述】:

我发现我的 CanActivate 防护 (Angular 10.2.5) 出现了奇怪的行为:

export class VersionGuardService implements CanActivate {

  constructor(private router: Router, private http: HttpClient){
  }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
    console.log("In the Guard");
    return this.http.request<any>('get',`https://jsonplaceholder.typicode.com/users`).pipe(
       tap(resp => console.log("Response: ", resp)),
       map(resp => false)
    );

    //return of(false);
  }
}

app-routing.module.ts 中的路由如下所示:

const routes: Routes = [    
    {
      path: 'login',
      component: LoginComponent,
      canActivate: [VersionGuardService]
    },
    {
      path: 'logout',
      component: LogoutComponent
    },
    {
      path: 'error',
      component: ErrorComponent
    },
    {
      path: '',
      redirectTo: 'login',
      pathMatch: 'full'
    }
];

如果我使用上述代码调用应用程序,我会收到 Too many calls to Location or History APIs within a short timeframe 错误(在 Firefox 中)。当我在浏览器中检查控制台输出时 - 确实有很多(近 200 个)条目带有 In the Guard 消息。如果我检查开发工具中的网络选项卡,我会在网络开发工具选项卡的“已转移”列中看到大量远程服务 https://jsonplaceholder.typicode.com/users 上的 GET 调用和 NS_BINDING_ABORTED 消息。

编辑 1 http 调用的流不提供任何数据(控制台日志中没有以“响应:”开头的条目。因此,http 调用后如何构造管道不是问题。

问题是为什么会这样?是什么原因导致 canActivate 方法执行了多次?

例如,如果我删除 http 调用并保持这样:

@Injectable()
export class VersionGuardService implements CanActivate {

  constructor(private router: Router, private http: HttpClient){
  }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
    console.log("In the Guard");
    return of(false);
  }
}

它按预期工作(在 Firefox 控制台中只有一个条目“In the Guard”)。

我想使用 Guard 的原因是在网站初始化时检查应用程序版本兼容性(与后端服务),并决定加载登录窗口或重定向到错误消息站点。

编辑 2 如果我将警卫移动到路线中的“稍后”链接(我的意思是:稍后在应用程序中执行的链接)并且警卫按预期工作。所以我认为这是应用程序初始化的问题,所以我在第一个链接上准备了带有保护的 stackblitz: https://stackblitz.com/edit/angular-ivy-qgfdk3 它也可以按预期工作。

提前感谢您的帮助!

【问题讨论】:

  • 请尝试在 http 请求中添加 take(n) 运算符和 catchError(() => of(false)) 块
  • 不幸的是,事实并非如此,流不提供任何数据,我提供了额外的描述来标记

标签: angular canactivate


【解决方案1】:

经过几个小时的代码检查,发现在代码的其他地方定义了一个 HTTP 拦截器。棘手的部分是,如果没有身份验证令牌,Http 拦截器将重定向到“/login”。因此,在我在“/login”路由上添加了带有 http 调用的 CanActivate 保护(不需要 auth 标头)之后 - 灾难已经准备好:用户 -> /login -> CanActivate -> http 调用 -> /login (因为没有身份验证header) -> CanActivate -> http call -> /login 等循环到浏览器Too many calls to Location or History APIs within a short timeframe 在使 HTTP 拦截器有条件地工作后,解决方案开始按预期工作。

【讨论】:

    猜你喜欢
    • 2017-07-26
    • 2020-02-14
    • 2017-03-28
    • 2018-01-02
    • 1970-01-01
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多