Angular 中的路由器拦截器是一个非常有用和强大的功能,它允许我们在发送 HTTP 请求时拦截、修改、中断和继续它们。路由器拦截器不仅仅限于 HTTP 请求,它还可以拦截路由导航事件,从而允许我们在用户导航到某个路由前执行某些任务。
在本文中,我们将深入探讨 Angular 中的路由器拦截器,并介绍如何使用它们来完成常见的任务。本文内容详细、深入,希望读者可以从中获取学习和指导意义。
拦截器的基本概念
在 Angular 中,路由器拦截器实际上就是一个实现了 HttpInterceptor
接口的类。该接口定义了一个 intercept
方法,该方法接收两个参数:一个 HttpRequest
对象和一个 HttpHandler
对象。
HttpRequest
对象表示即将发送的 HTTP 请求,我们可以在 intercept
方法中修改它,例如添加或修改请求头或查询参数,或者将请求体设为一个特定的固定值。然后,我们可以将修改后的请求发送到服务器。
HttpHandler
对象允许我们进一步处理请求。它有一个 handle
方法,该方法接收一个 HttpRequest
对象,并返回一个 Observable<HttpEvent<any>>
。我们可以在 handle
方法中订阅这个 Observable
,以便在响应返回时执行某些操作。例如,我们可以处理响应,提取消息或错误,或者将响应流传递给下一个拦截器。
使用拦截器修改请求
让我们看一个简单的例子,演示如何使用拦截器来修改 HTTP 请求。为了让我们的示例更加逼真,我们将演示如何向请求中添加身份验证头来验证用户是否已经登录。首先,我们需要创建一个新的拦截器类:
// javascriptcn.com 代码示例 import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http'; @Injectable({ providedIn: 'root' }) export class AuthInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler) { const authToken = 'example-auth-token'; const authReq = req.clone({ headers: req.headers.set('Authorization', `Bearer ${authToken}`) }); return next.handle(authReq); } }
在这个示例中,我们创建了一个名为 AuthInterceptor
的拦截器类,它实现了 HttpInterceptor
接口。在 intercept
方法中,我们首先从本地存储或其他位置获取身份验证令牌。然后,我们克隆原始请求,并使用 set
方法设置新的身份验证头,将身份验证令牌放在 'Bearer '
前缀之后。最后,我们将修改后的请求传递给 next.handle
方法,让它继续进行。
现在,我们需要将这个拦截器添加到我们的头文件中:
// javascriptcn.com 代码示例 import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { AuthInterceptor } from './auth.interceptor'; @NgModule({ providers: [{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }] }) export class AppModule { }
在这个例子中,我们使用 HTTP_INTERCEPTORS
常量来声明一个 AuthInterceptor
类型的提供程序,并将其添加到我们的模块提供程序中。我们通过设置 multi
标志来告诉 Angular,我们将添加多个拦截器,并让它合并提供程序。
现在我们已经创建了一个简单的拦截器,并将它添加到了我们的头文件中。当我们发送 HTTP 请求时,它将被拦截,并在其中添加身份验证头。
中断请求
有时,我们可能需要在某些条件满足时中断请求,例如用户未登录或请求数据无效时。在这种情况下,我们可以返回一个 Observable
,它在 intercept
方法中完成,以便完全中断请求。让我们看一个简单的例子:
// javascriptcn.com 代码示例 import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler, HttpErrorResponse } from '@angular/common/http'; import { Observable, throwError } from 'rxjs'; import { catchError } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class InvalidRequestInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<any> { if (!isValidRequest(req)) { return throwError(new HttpErrorResponse({ status: 400, statusText: 'Invalid request' })); } return next.handle(req).pipe( catchError((error: HttpErrorResponse) => { if (error.status === 401) { redirectToLoginPage(); return throwError(error); } return throwError(error); }) ); } }
在这个示例中,我们创建了一个名为 InvalidRequestInterceptor
的拦截器类。在 intercept
方法中,我们首先检查请求是否有效。如果请求无效,我们返回一个 Observable
,它发出一个 HttpErrorResponse
对象,其中包含状态码 400 和错误消息“Invalid request”。
如果请求有效,我们使用 next.handle
方法发送请求,同时使用 catchError
操作符来捕获可能的错误。如果错误的状态码为 401,则我们重定向到登录页面,并返回一个 Observable
,以便停止响应流并中断请求。否则,我们仅仅通过 throwError
操作符将错误传递给下一个拦截器或响应流。
拦截路由导航事件
拦截器不仅可以用于 HTTP 请求,还可以用于路由导航事件。通过这种方式,我们可以在用户导航到某个路由之前执行某些任务,例如检查用户是否已登录或是否具有足够的权限。
在 Angular 中,路由器拦截器使用 CanActivate
接口实现路由导航守卫。让我们看一个简单的例子:
// javascriptcn.com 代码示例 import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree } from '@angular/router'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> { return isLoggedIn().pipe( map(loggedIn => { if (loggedIn) { return true; } else { return redirectToLoginPage(); } }) ); } }
在这个示例中,我们创建了一个名为 AuthGuard
的路由器拦截器。在 canActivate
方法中,我们首先检查用户是否已登录。如果用户已登录,我们返回一个发出 true
的 Observable
,表示用户已通过守卫。否则,我们重定向到登录页面,并返回一个发出 UrlTree
对象的 Observable
,该对象表示重定向 URL。
总结
Angular 中的路由器拦截器是一个非常强大的功能,它为我们提供了灵活和可配置的方式来拦截和修改 HTTP 请求和路由导航事件。在本文中,我们深入探讨了路由器拦截器的基本概念,介绍了如何使用拦截器来完成常见任务,例如修改请求、中断请求和拦截路由导航事件。希望本文能对读者有所帮助,让他们更好地理解 Angular 中的路由器拦截器,并在实际项目中灵活使用。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/653329387d4982a6eb69466e