如果 HTTP GET 请求 returns 没有数据,如何保护路由?

How to guard route if HTTP GET request returns no data?

下面是我的 Angular 应用程序中的一个 table。它填充了来自 employees.json:

的数据
<tbody>
    <tr *ngFor="let employee of employees">
        <td (click)="viewEmployeeProfile(1, employee.id)">{{employee.fullName}}
        </td>
    </tr>
</tbody>

当用户点击一个名字时,employeeId 被传递给这个方法:

viewEmployeeProfile(roleId: number, employeeId: number) {
    this._router.navigate(['/profile', roleId, employeeId]);
}

这是我的 AppRouting 模块中的路线:

const routes: Routes = [
  {
    path: 'profile/:role/:id',
    component: ProfileComponent,
    // canActivate: [RequireEmployeeProfileGuardGuard]
  },
  { 
    path: 'page-not-found', 
    component: PageNotFoundComponent 
  },
  { 
    path: '**', 
    component: PageNotFoundComponent
  }
];

示例路径:http://localhost:4200/profile/1/4

当用户路由到Profile组件时,调用这段代码:

profile.component.ts:

ngOnInit() {
    this.route.paramMap.subscribe(params => {
    const roleId = +params.get('role');
    const empId = +params.get('id');
    this.getEmployee(empId);
    });

}

getEmployee(id: number) {
    this.employeeService.getEmployee(id).subscribe(
      (employee: IEmployee) => this.displayEmployee(employee),
      (err: any) => console.log(err)
    );
}

displayEmployee(employee: IEmployee) {
    this.employee.fullName = employee.fullName;
}

profile.component.html:

<tr>
    <td><b>Full Name</b></td>
    <td>{{employee.fullName}}</td>
</tr>

这是我的 employee.service:

baseUrl = 'http://localhost:3000/employees';

getEmployee(id: number): Observable<IEmployee> {
    return this.httpClient.get<IEmployee>(`${this.baseUrl}/${id}`)
        .pipe(catchError(this.handleError));
    }

此代码运行良好,并按预期显示数据。

目前,如果我导航到 http://localhost:4200/profile/1/123456789 之类的路线,其中 employeeId 不存在,则 Profile 组件显示时没有数据。

相反,我希望将用户带回 PageNotFound 组件。

这是我当前的路线:

const routes: Routes = [
  { path: 'profile/:role/:id', component: ProfileComponent },
  { path: '**', component: PageNotFoundComponent }
];

有人可以告诉我我需要做哪些改变才能实现这个吗?

您可以修改您的 getEmployee 方法来执行类似

getEmployee(id: number) {
    this.employeeService.getEmployee(id).subscribe(
      (employee: IEmployee) => {
         if(employee){
          this.displayEmployee(employee)
        }else{
          //redirect to page not found here
       }
      },
      (err: any) => console.log(err)
    );
}

将以下路由添加到 AppRouting 模块

{path: '404', component: NotFoundComponent},
{path: '**', redirectTo: '/404'}

以上路由将在根级别和任何嵌套子级中捕获不正确的路由,因为 well.put 此路径作为路由模块中的最后一个路径

如果记录计数为 0 或 null

,则从 getEmployee 方法调用 gotoHeroes 方法
gotoHeroes() {
  this.router.navigate(['/404']);
}

这对 CanActivate 后卫来说是一个绝佳的机会。

自 Angular 7.1.0 以来,路由守卫现在可能 return 一篇 URLTree which gives us some really cool flexibility in our guards. Here 是一篇很好的文章,其中介绍了更改及其含义/如何使用它们。

我建议你创建你的守卫。类似于以下内容:

import { Injectable } from '@angular/core';
import { CanActivate, Router, UrlTree, ActivatedRouteSnapshot } from '@angular/router';
import { Observable, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
// import your employee service here

@Injectable()
export class RequireEmployeeProfileGuard implements CanActivate {
  constructor(private router: Router, private employeeService: EmployeeService) {
  }

  canActivate(route: ActivatedRouteSnapshot): Observable<boolean | UrlTree> {
    return this.employeeService.getEmployee(+route.paramMap.get('id')).pipe(
      catchError(() => of(false)),
      map(employee => !!employee || this.router.parseUrl('page-not-found'))
    );
  }
}

从这里,转到你的路由模块,导入这个守卫并将它添加到你的路由中,如下所示:

{ 
  path: 'profile/:role/:id', 
  component: ProfileComponent,
  canActivate: [RequireEmployeeProfileGuard]
}

我也可能会为错误组件定义一个明确命名的路由,例如:

{ 
  path: 'page-not-found', 
  component: PageNotFoundComponent 
}

那么上面守卫的'absolute-redirect-url-here'就变成了'page-not-found'.

此外,由于您仍希望对无效 URL 进行 'catch-all' 处理,因此您可能需要这样的路由:

{ 
  path: '**', 
  redirectTo: 'page-not-found'
}

那么这是如何工作的?

它可能看起来很复杂,但其实它的核心非常简单。神奇之处在于我们添加到守卫的 canActivate() 方法:

我们从 employeeService 请求员工资料,并使用 double-not 运算符将其转换为布尔值(基本上,检查 "do we have a matching employee profile")。如果这转换为 false,则 URLTree 被 returned,它将路由器重定向到指定的绝对路由。

当任何路由被解析时,Angular 将 运行 以 pre-defined 的顺序通过所有附加到它的守卫。如果 任何 守卫 'fail' 则不会加载该路线。