如果HTTP GET请求未返回数据,如何保护路由? [英] How to guard route if HTTP GET request returns no data?

查看:217
本文介绍了如果HTTP GET请求未返回数据,如何保护路由?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是我的Angular应用中的表格.它填充了来自employees.json:

Below is a table in my Angular app. It is populated with data from employees.json:

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

当用户单击名称时,employeeId会传递给此方法:

When the user clicks on a name, the employeeId is passed to this method:

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

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

Here is the route in my AppRouting module:

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组件时,此代码称为:

When the user routes to theProfile component, this code is called:

profile.component.ts:

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:

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));
    }

此代码可以正常工作,&按预期显示数据.

This code is working fine, & displays data as expected.

当前,如果我导航到诸如http://localhost:4200/profile/1/123456789的路由,而该employeeId不存在,则显示Profile组件时将不显示任何数据.

Currently, if I navigate to a route such as http://localhost:4200/profile/1/123456789, where that employeeId does not exist, the Profilecomponent is displayed with no data.

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

Instead of this, I would want the user to be brought back to the PageNotFound component.

这是我当前的路线:

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

有人可以告诉我实施此操作需要做哪些更改吗?

Can someone please tell me what changes I need to make to implement this?

推荐答案

对于 CanActivate 卫队.

自Angular 7.1.0起,路由保护程序现在可以返回 URLTree ,它为我们提供了一些帮助在我们的后卫中非常酷的灵活性. 这里很不错有关更改及其含义/使用方法的文章.

Since Angular 7.1.0, route guards may now return a URLTree which gives us some really cool flexibility in our guards. Here is a nice article that goes over the changes and what they mean / how they can be used.

我建议您建立警卫队.类似于以下内容:

I would suggest you create your guard. Something like the following:

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'))
    );
  }
}

从这里开始,只需转到路由模块",导入此防护并将其添加到您的路由中,如下所示:

From here, just go to your Routing Module, import this guard and add it to your route like this:

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

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

I would also probably define an explicitly named route for the error component too like:

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

因此,上面的后卫中的'absolute-redirect-url-here'将变为'page-not-found'.

So then 'absolute-redirect-url-here' from the guard above would become 'page-not-found'.

此外,由于您仍然希望对无效的网址采用全包"格式,因此您可能希望使用类似以下的路由:

Also, since you would still want to have a 'catch-all' case for invalid URLs, you would probably want a route like:

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

那么这是怎么工作的?

它可能看起来很复杂,但实际上它非常简单.魔术在于我们添加到后卫的canActivate()方法中:

It might look complex but it's very simple at its core really. The magic is in the canActivate() method that we added to the guard:

我们正在从employeeService请求雇员资料,并使用double-not运算符将其转换为布尔值(基本上,检查我们是否有匹配的雇员资料").如果将其转换为false,则返回URLTree,它将把路由器重定向到指定的绝对路由.

We are requesting the employee profile from the employeeService and converting it to a boolean using the double-not operator (basically, checking "do we have a matching employee profile"). If this converts to a false then the URLTree is returned which will redirect the router to the specified, absolute route.

当解决任何一条路线时,Angular将按照预定义的顺序遍历所有与之相连的防护装置.如果警卫的任何失败",则不会加载该路由.

When any route is being resolved, Angular will run through all the guards attached to it in a pre-defined order. If any of the guards 'fail' then the route won't be loaded.

这篇关于如果HTTP GET请求未返回数据,如何保护路由?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆