新项目开发整理(二)使用Proxy为原生fetch做拦截器

3,227 阅读1分钟

相信大家使用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值了~