今天這一章節主要介紹 攔截器
目錄結構:
攔截器
先問什麼是攔截器?
可以從字面意思理解大概就是攔截數據,主要運用在發起請求前或請求返回數據後對數據進行處理,可以運用在登錄、處理一些格式化數據之類的。
按照請求的時間不同分爲:請求前的 請求攔截器,請求後的 響應攔截器
在 types/index.ts
中新增代碼
// ...
// 最後加入
export interface AxiosInterceptorManage<T>{
use(resolved:ResolvedFn<T>,rejected?:RejectedFn):number,
eject(id:number):void
}
export interface ResolvedFn<T>{
(val:T) : T | Promise<T>
}
export interface RejectedFn {
(error: any) : any,
}
其中 <T>
表示 泛型 (之前說過的)
新增文件 core/InterceptorManager.ts
import {RejectedFn,ResolvedFn} from '../types/index';
interface Interceptor<T>{
resolved:ResolvedFn<T>,
rejected?:RejectedFn,
}
export default class InterceptorManager<T>{
private interceptors:Array<Interceptor<T> | null>
constructor(){
this.interceptors = []
}
use(resolved:ResolvedFn<T>,rejected?:RejectedFn):number{
this.interceptors.push({
resolved,
rejected,
})
return this.interceptors.length -1;
}
forEach(fn:(interceptor: Interceptor<T>) => void) : void {
this.interceptors.forEach(interceptor => {
if(interceptor !== null) {
fn(interceptor);
}
})
}
eject(id:number):void{
if(this.interceptors[id]) {
this.interceptors[id] = null;
}
}
}
定義一個 InterceptorManager 類,其中有一個 use 方法,主要用來將回調函數添加到 interceptors 中,並返回其下標;eject 方法用在下標刪除回調函數; forEach 遍歷回調函數
core/Axios.ts
// ...
import InterceptorManager from './InterceptorManager';
interface Interceptors{
request: InterceptorManager<AxiosRequestConfig>
response: InterceptorManager<AxiosResponse>
}
interface PromiseChain<T> {
resolved:ResolvedFn<T> | ((config:AxiosRequestConfig) => AxiosPromise)
rejected?:RejectedFn,
}
export default class Axios{
interceptors: Interceptors
constructor(){
this.interceptors = {
request : new InterceptorManager<AxiosRequestConfig>(),
response :new InterceptorManager<AxiosResponse>(),
}
}
request(url: any, config?:any):AxiosPromise {
// ...
const chain:PromiseChain<any>[] = [{
resolved: dispatchRequest,
rejected: undefined,
}] // 添加要發起請求
this.interceptors.request.forEach(interceptor => {
chain.unshift(interceptor)
}) // 請求攔截器放在 請求 前
this.interceptors.response.forEach(interceptor => {
chain.push(interceptor)
}) // 響應攔截器放在 請求 後
let promise = Promise.resolve(config)
while(chain.length) {
const {resolved,rejected} = chain.shift()!
promise = promise.then(resolved,rejected);
} // 遍歷 chain ,實現調用
return promise;
}
// ...
}
這一段代碼是核心代碼,將所有的攔截器和請求放在 chain 數組中,依次彈出借用 Promise 執行。
實現調用:
import axios from '../../src/index'
axios.interceptors.request.use(config => {
config.headers.test += '1'
return config
})
axios.interceptors.request.use(config => {
config.headers.test += '2'
return config
})
axios.interceptors.request.use(config => {
config.headers.test += '3'
return config
})
axios.interceptors.response.use(res => {
res.data += '1'
return res
})
let interceptor = axios.interceptors.response.use(res => {
res.data += '2'
return res
})
axios.interceptors.response.use(res => {
res.data += '3'
return res
})
axios.interceptors.response.eject(interceptor)
axios({
url: '/interceptor/get',
method: 'get',
headers: {
test: ''
}
}).then((res) => {
console.log(res.data)
})
返回的數據會多加 13
,而 headers.test
等於 321
注意:請求攔截器越後面註冊就越靠前,響應攔截器反之。因爲請求攔截器用的是 unshift,響應攔截器用的是 push
就寫到這裏吧。