欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

Angular 拦截器配置 有大用

Angular 拦截器配置        

创建AuthInterceptor.ts文件

import { AuthService } from './../app.service';
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http';
import { environment } from 'src/environments/environment';
import { Observable } from 'rxjs';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(private authService: AppService) {}
  
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  // 获取本地存储的token值,
    const authToken = this.authService.getAuthorizationToken();
    // 若token存在,则对请求添加请求头
    // 并格式化处理url地址,简化service中接口地址的编辑
    if (authToken) {
      const authReq = req.clone({
        headers: req.headers.set('Authorization', 'bearer' + authToken),
        url: environment.api_endpoint + req.url
      });
      return next
      // 返回处理后的请求
      .handle(authReq) 
      // 返回结果错误处理
      .pipe(catchError(error => this.auth.handleError(error)));
    }
    // 若token不存在,则不对请求进行处理
    return next.handle(req);
  }
}


                
                
                
                
       

挂载authInterceptor.ts文件

// 一般在主模块中注入,使系统所有请求都被拦截
@ngModule({
	declarations: [],
	imports:[],
	providers: [
		{
			provide: HTTP_INTERCEPTORS,
	      	useClass: AuthInterceptor,
	      	multi: true
		}
	]
})

                
                
                
                
       

允许创建多个拦截器

import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { NoopInterceptor } from './noop-interceptor';
import { AuthInterceptor } from './authInterceptor';
// 将多个拦截器添加至一个List中,然后一次性挂载
export const httpInterceptorProviders = [
  { provide: HTTP_INTERCEPTORS, useClass: NoopInterceptor, multi: true },
  { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
];

                
                
                
                
                                                                                                                                       
import { httpInterceptorProviders } from './httpInterceptorProviders.ts'
@ngModule({
	declarations: [],
	imports:[],
	providers: [ httpInterceptorProviders ]
})
                
                
                
                
     

                   


                   


angular6之http请求拦截器

在前端项目中我们往往需要对每次请求做一些统一的处理,比如请求结果session过期处理,在header头部加上验证参数token等等,这个时候就需要用到拦截器。

由于angular中http请求,依赖@angular/common/http模块,将HttpInterceptor,HttpRequest,HttpResponse等对象引入

1
2
3
4
5
6
7
8
import {                                        
    HttpInterceptor,                                        
    HttpRequest,                                        
    HttpHandler,                                        
    HttpErrorResponse,                                        
    HttpHeaderResponse,                                        
    HttpResponse,                                        
} from '@angular/common/http';                                        

  引入模块后,我们要实现HttpInterceptor接口

1
2
3
export class MyInterceptor implements HttpInterceptor {                                        
    constructor (){}                                        
}                                        

  具体的拦截器部分实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<                                        
    | HttpHeaderResponse                                        
    | HttpResponse<any>                                        
  > { <br>                                        
        let req = request.clone({param1:'',param2:''});//这里可以在请求中加参数                                        
        return next.handle(req).pipe( mergeMap((event: any) => {                                        
            // 正常返回,处理具体返回参数                                        
            if (event instanceof HttpResponse && event.status === 200)                                        
                return this.handleData(event);//具体处理请求返回数据                                        
                return of(event);                                        
        }),                                        
        catchError((err: HttpErrorResponse) => this.handleData(err)))                                        
      }                                        

  在平常我们的业务中往往服务端返回200,但是有可能是业务上出错,比如说请求的参数不对,session过期没有通过验证等等,这个时候需要我们做统一处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private handleData(                                        
        event: HttpResponse<any> | HttpErrorResponse,                                        
      ): Observable<any> {                                        
        // 业务处理:一些通用操作                                        
        switch (event.status) {                                        
          case 200:                                        
            if (event instanceof HttpResponse) {                                        
                const body: any = event.body;                                        
                if (body && body.rc == 3) {                                        
                    this.goTo('/test');                                        
                }                                        
            }                                        
            break;                                        
          case 401: // 未登录状态码                                        
            this.goTo('/login');                                        
            break;                                        
          case 404:                                        
          case 500:                                        
           ……                                        
          break;                                        
          default:                                        
          return of(event);                                        
      }                                        

  这里我们对不同返回状态做同的统一处理。

最后我们将拦截器模块引入到app.module.ts跟模块中。基本就完成了

1
2
3
4
5
6
7
import { MyInterceptor } from './myIntercept'                                        
@NgModule({                                        
     ……                                        
     providers: [{ provide: HTTP_INTERCEPTORS, useClass: MyInterceptor, multi:                                        
                     true }]                                        
    ……                                        
})                                        

  注:本文部分代码参考了ng-alain中拦截器的写法,如果想了解可以参考https://github.com/cipchk/ng-alain        


       

来自  https://www.cnblogs.com/leejay6567/p/9462758.html        

Angular 常用拦截器

       
0.096                字数 73阅读 495            


1、实现步骤

  • 实现 HttpInterceptor 接口

import { Injectable } from "@angular/core";
import { HttpEvent, HttpRequest, HttpHandler, HttpInterceptor } from "@angular/common/http";

import { Observable } from "rxjs";

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
   ...
  }
}
   
  • 注册 Provider

import { AuthInterceptor } from "./interceptors/auth.interceptor";

({
  declarations: [AppComponent],
  imports: [BrowserModule, HttpClientModule],
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

   

2、常见拦截器

  • AuthInterceptor 自定义请求头,如 token 之类

// AuthInterceptor.ts
import { Injectable } from "@angular/core";
import { HttpEvent, HttpRequest, HttpHandler, HttpInterceptor } from "@angular/common/http";

import { Observable } from "rxjs";

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    const clonedRequest = req.clone({
      headers: req.headers.set("X-CustomAuthHeader", "iloveangular")
    });
    console.log("new headers", clonedRequest.headers.keys());
    return next.handle(clonedRequest);
  }
}

// AppModule.ts
import { AuthInterceptor } from "./interceptors/auth.interceptor";

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, HttpClientModule],
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}
   
  • LogInterceptor 请求日志拦截器,主要记录请求花费时间、状态等

// LogInterceptor.ts
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpResponse } from '@angular/common/http';
import { finalize, tap } from 'rxjs/operators';

@Injectable()
export class LogInterceptor implements HttpInterceptor {

  constructor(private loggerService: LoggerService) {}

  intercept(req: HttpRequest<any>, next: HttpHandler) {
    const startTime = Date.now();
    let status: string;

    return next.handle(req).pipe(
        tap(
          event => {
            status = '';
            if (event instanceof HttpResponse) {
              status = 'succeeded';
            }
          },
          error => status = 'failed'
        ),
        finalize(() => {
          const elapsedTime = Date.now() - startTime;
          const message = req.method + " " + req.urlWithParams +" "+ status 
          + " in " + elapsedTime + "ms";
          
          console.log(message);
        })
    );
  }
}
// AppModule.ts
@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, HttpClientModule],
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
    { provide: HTTP_INTERCEPTORS, useClass: LogInterceptor, multi: true }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}
   
  • CacheInterceptor 请求缓存控制器

// Cache.ts
import { HttpRequest, HttpResponse } from '@angular/common/http';

export interface Cache {
  get(req: HttpRequest<any>): HttpResponse<any> | null;
  put(req: HttpRequest<any>, res: HttpResponse<any>): void;
}

export const MAX_CACHE_AGE = 30000; // 单位为毫秒

export interface CacheEntry {
  url: string;
  response: HttpResponse<any>;
  entryTime: number;
}

// CacheService.ts
import { Injectable } from "@angular/core";
import { HttpRequest, HttpResponse } from "@angular/common/http";

import { Cache } from "./cache";
import { CacheEntry, MAX_CACHE_AGE } from "./cache.entry";

@Injectable({
  providedIn: "root"
})
export class CacheService implements Cache {
  cacheMap = new Map<string, CacheEntry>();

  constructor() {}

  get(req: HttpRequest<any>): HttpResponse<any> | null {
    // 判断当前请求是否已被缓存,若未缓存则返回null
    const entry = this.cacheMap.get(req.urlWithParams);
    if (!entry) return null;
    // 若缓存命中,则判断缓存是否过期,若已过期则返回null。否则返回请求对应的响应对象  
    const isExpired = Date.now() - entry.entryTime > MAX_CACHE_AGE;
    console.log(`req.urlWithParams is Expired: ${isExpired} `);
    return isExpired ? null : entry.response;
  }

  put(req: HttpRequest<any>, res: HttpResponse<any>): void {
    // 创建CacheEntry对象  
    const entry: CacheEntry = {
      url: req.urlWithParams,
      response: res,
      entryTime: Date.now()
    };
    console.log(`Save entry.url response into cache`);
    // 以请求url作为键,CacheEntry对象为值,保存到cacheMap中。并执行
    // 清理操作,即清理已过期的缓存。
    this.cacheMap.set(req.urlWithParams, entry);
    this.deleteExpiredCache();
  }

  private deleteExpiredCache() {
    this.cacheMap.forEach(entry => {
      if (Date.now() - entry.entryTime > MAX_CACHE_AGE) {
        this.cacheMap.delete(entry.url);
      }
    });
  }
}

// CacheInterceptor.ts
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpResponse, HttpHandler } from '@angular/common/http';
import { of } from 'rxjs';
import { tap } from 'rxjs/operators';

import { CacheService } from '../cache.service';

const CACHABLE_URL = "http://jsonplaceholder.typicode.com";

@Injectable()
export class CacheInterceptor implements HttpInterceptor {
    constructor(private cache: CacheService) {}

    intercept(req: HttpRequest<any>, next: HttpHandler) {
        // 判断当前请求是否可缓存
        if (!this.isRequestCachable(req)) { 
           return next.handle(req); 
        }
        // 获取请求对应的缓存对象,若存在则直接返回该请求对象对应的缓存对象
        const cachedResponse = this.cache.get(req);
        if (cachedResponse !== null) {
           return of(cachedResponse);
        }
        // 发送请求至API站点,请求成功后保存至缓存中
        return next.handle(req).pipe(
           tap(event => {
              if (event instanceof HttpResponse) {
                this.cache.put(req, event); 
              }
           })
        );
    }
    
    // 判断当前请求是否可缓存
    private isRequestCachable(req: HttpRequest<any>) {
        return (req.method === 'GET') && (req.url.indexOf(CACHABLE_URL) > -1);
    }
}

// AppModule.ts 
@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, HttpClientModule],
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
    { provide: HTTP_INTERCEPTORS, useClass: LogInterceptor, multi: true },
    { provide: HTTP_INTERCEPTORS, useClass: CacheInterceptor, multi: true }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}
   
  • ResponseInterceptor 接口错误统一处理

import { Injectable } from '@angular/core'
import {
  HttpEvent,
  HttpRequest,
  HttpResponse,
  HttpErrorResponse,
  HttpHandler,
  HttpInterceptor
} from '@angular/common/http'
import { Observable } from 'rxjs'
import { Router } from '@angular/router'
import { tap } from 'rxjs/operators'
import { MessageService } from '../providers'

@Injectable()
export class ResponseInterceptor implements HttpInterceptor {
  constructor(private messageService: MessageService, private router: Router) {}
  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    return next.handle(req).pipe(
      tap(
        response => {
          if (response instanceof HttpResponse) {
            if (
              response.status === 200 &&
              response.body &&
              parseInt(response.body.code, 10) !== 0
            ) {
              const message = response.body.message || '未知错误'
              if (response.body.code === 109) {
                // token 失效
                this.router.navigate(['/login'])
              }
              this.messageService.addErrorMessage(message)
            }
          }
        },
        error => {
          if (error instanceof HttpErrorResponse) {
            if (error.status >= 500) {
              this.messageService.addErrorMessage(
                `服务器内部错误 ${error.status}`
              )
            } else if (error.status >= 400 && error.status < 500) {
              this.messageService.addErrorMessage(
                `客户端参数错误 ${error.status}`
              )
            }
          }
        }
      )
    )
  }
}

   


1人点赞        
   
Angular    


普通分类: