如何从路由器事件订阅返回路由守卫的值

时间:2021-04-14 14:48:11

标签: angular rxjs reactive-programming router

我正在尝试基于用户的权限实施安全路由。没有特定权限的用户无法访问该路由。这就是我在路由中传递正确名称的原因(惰性模块路由)。但是,我发现获取懒惰的路线数据有点复杂。我必须订阅路由器事件。但是,订阅后,我找不到将 false 或 true 返回到 Canactivate 的方法。

这是我的 canActivate 代码:

 canActivate() {
    this.router.events
      .pipe(
        filter((event) => event instanceof NavigationEnd),
        map(() => this.activatedRoute),
        map((route) => {
          while (route.firstChild) {
            route = route.firstChild;
          }
          return route;
        }),
        mergeMap((route) => route.data))
      .subscribe((event) => {
        const right = event.right; // getting the right name from the route data. 
        const rights = this.localStorageService.getLocalStorageItem('rights');

        if (right) {
          if (rights.includes(right)) {
            // I need to return true from here 
          } else {
            // I need to return false from here 
          }
        }
      });
  }

而且,这是我的路线代码:

const routes: Routes = [{ path: ':id', component: ProfileComponent, 
data: { right: 'VIEW_PROFILE' }, canActivate: [RightRouteGuardService]}];

1 个答案:

答案 0 :(得分:1)

Angular 路由守卫可以返回 Observable<boolean> | Promise<boolean> | boolean。我想你想返回一个布尔值,但如果我是你,我会返回 Observable<boolean>

试试这个:

canActivate(): Observable<boolean> {
  return this.router.events
      .pipe(
        filter((event) => !!event), // !! add this filter !!
        filter((event) => event instanceof NavigationEnd),
        map(() => this.activatedRoute),
        map((route) => {
          while (route.firstChild) {
            route = route.firstChild;
          }
          return route;
        }),
        mergeMap((route) => route.data),
        // map will return true false for us
        map(event => {
          const right = event.right; // getting the right name from the route data. 
          const rights = this.localStorageService.getLocalStorageItem('rights');
          if (right) {
            if (rights.includes(right)) {
              return true;
            } else {
              return false;
            }
          }
        }),
      );
}

你不需要再订阅了,这个 observable 的第一次发射就会为你返回 true 和 false。

========================== 编辑 ==================== ====== 不要注入路由器并侦听事件,因为路由器尚未完成导航并且您的 filterNavigationEnd 将不允许它继续进行,并且当时没有任何事件.

我已经解决了这个问题:

import { Injectable } from "@angular/core";
import {
  ActivatedRouteSnapshot,
  CanActivate,
  RouterStateSnapshot
} from "@angular/router";

@Injectable({
  providedIn: "root"
})
export class RightRouteGuardService implements CanActivate {
  constructor() {}

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean{
    let right = route.data.right;
    console.log({ right });
    const rights = ['VIEW_STUDENT'];
    if (rights.includes(right)) {
      return true;
    } else {
      return false;
    }
  }
}

canActivate 方法接受两个属性,您可以使用这些属性读取相关路由的数据属性。

我受到了这个post的启发。