相信大家使用axios的话,对拦截器肯定不陌生,对于使用JWT方案来做用户身份的项目中,我们通常在拿到token后通过axios自带的拦截器,为请求在请求头中加上token,免去了在每个请求的地方手动加token的麻烦,但是当我们要在项目中使用fetch做http请求时,没有自带的拦截器供我们使用,所以这次分享一下使用es6的Proxy来为fetch做一个拦截器。
什么是Proxy
proxy就是在目标对象触发某种行为时,做一层拦截,拦截该行为,并对该行为做自定义处理后,返回新的行为结果,像我们平时在开发环境常用的http的代理就是拦截了我们本地发出的请求,并对该请求进行转发实现跨域,关于proxy更多详细特性,请看ECMAScript 6入门 —— Proxy,下面我们用一段简单代码展示proxy做了什么
let student = new Proxy({}, {
get: function(target, propKey,args) {
return `我的名字是${target[propKey]}`;
}
});
student.name = "小明"
student.name //"我的名字是小明"
如上所示我们对student对象的get属性做了一层拦截,然后在返回值前面加上了"我的名字是"并返回,这就是一个简单的Proxy应用
用proxy做fetch拦截器
先整理一下思路,我们要做的是在fetch请求发送到服务器之前,拦截这个请求,并在这个请求的请求头Authorization加上我们缓存的token值来做身份验证,假设我们的token存在sessionstorage中,下面是简单实现:
const httpRequest = new Proxy(window.fetch, {
apply: (target, obj, args) => {
let default_header = sessionStorage.getItem('token') ? {
headers:{
"Accept": "application/json",
"content-type": "application/json; charset=utf-8",
"Authorization":`${sessionStorage.getItem('token')}`
}
} : {
headers:{
"Accept": "application/json",
"content-type": "application/json; charset=utf-8"
}
}
args[1] = {...args[1],...default_header}
return target.apply(null,args);
}
// 拦截fetch的apply即调用行为,并统一加请求头
});
export const request = (url:string,obj:Object = {}):Promise<any> => {
return new Promise((resolve,reject)=>{
httpRequest(url,obj).then(s=>s.json()).then(result=>{
resolve(result)
}).catch(err=>{
reject(err)
})
})
}
//对fetch返回值进行处理并返回
有了上面的封装,我们在开发中发起http请求,只需要引入request并调用即可,无需传递多余参数,示例如下:
import { request } from "util.js"
request("/api/test").then(result => {
/*逻辑*/
}).catch(err => {
/*逻辑*/
})
request("/api/posttest",{method: "POST", body: JSON.stringfy(bodyData)}).then(result => {
/*逻辑*/
}).catch(err => {
/*逻辑*/
})
这样就不用手动每次加上token值了~