前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【秒懂】axios拦截器模式简单实现

【秒懂】axios拦截器模式简单实现

原创
作者头像
老码小张
修改2021-09-05 19:51:06
2.2K0
修改2021-09-05 19:51:06
举报
文章被收录于专栏:玩转全栈

Axios 是什么?

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。 今天这里主要是拦截器这里做一些分析,并且自动动手实现一个简化版本的便于理解。

拦截器的原理:

1、拦截器分为请求拦截器,和响应body拦截器

2、请求拦截器的主要作用,可以理解为给请求body加一下附带参数,如请求token,或者对请求做一些过滤,比如判定请求时一个非法请求时直接reject。

3、响应body拦截器的作用在于可以在框架级别对于响应body的内容进行合适的处理,比如401的http status code直接导航用到到登录页进行重新鉴权,亦或者直接做一个续期token的操作,并且在续期成功之后直接重放刚才的请求。

4、所以,感觉拦截器是axios的精华部分。

下面这个是完全参考axios写的一个请求和响应拦截器的简化版本

代码语言:javascript
复制
/**
 * 一个及其简单的axios版本
 */
class Firs {
    interceptors = {
      request: new InterceptorManger(),
      response: new InterceptorManger(),
    }
    constructor({ baseUrl, timeout, headers }) {
      this.baseUrl = baseUrl;
      this.timeout = timeout;
      this.headers = headers;
    }

    //请求真正发送在此处,axios的这里实现是根据node和浏览器的版本分别做了两个adapter
    dispatchRequest() {
      return new Promise((resolve, reject) => {
        try {
          console.log('dispatchRequest method execute...');
          setTimeout(() => {
            resolve('dispatchRequest response here!');
            // reject('1');
          }, 3000);
        } catch (e) {
          reject(e);
        }
      });
    }

    request() {
      let promise = Promise.resolve(this);
      let chain = [this.dispatchRequest, undefined];

      const requestInterceptorChain = [];
      while (this.interceptors.request.handlers.length > 0) {
        requestInterceptorChain.unshift(
          this.interceptors.request.handlers.shift(),
          this.interceptors.request.handlers.shift(),
        );
      }
      Array.prototype.unshift.apply(chain, requestInterceptorChain);
      chain  = chain.concat(this.interceptors.response.handlers);
      while (chain.length > 0) {
        promise = promise.then(chain.shift(), chain.shift());
      }
      return promise;
    }
}

class InterceptorManger {
    handlers = []
    use(fulfilled, rejected) {
      this.handlers.push(
        fulfilled,
        rejected,
      );
    }
}


//  下面是验证逻辑
const fire = new Firs({
  baseUrl: 'https://baseurl.com/',
  timeout: 4000,
  headers: {
    xDev: 'xDev',
  },
});

//添加两个请求拦截器
fire.interceptors.request.use((config) =>  {
  // eslint-disable-next-line no-param-reassign
  config.headers.interceptors = '1111';// 修改一个header试试
  console.log(`request interceptor 1 execute..${JSON.stringify(config)}`);
  //   return config;
  return Promise.reject('用户需要登录');
}, (err) =>  {
  console.log(`request interceptor 1 ${err}`);
  return Promise.reject(err);
});
fire.interceptors.request.use((config) =>  {
  console.log(`request interceptor 2 execute..${JSON.stringify(config)}`);
  return config;
}, (err) =>  {
  console.log(`request interceptor 2 ${err}`);
  return Promise.reject(err);
});
//添加一个响应拦截器
fire.interceptors.response.use((response) =>  {
  console.log(`response interceptor 1 execute..${response}`);
  return response;
}, (err) =>  {
  console.log(`response interceptor 1 ${err}`);
  return Promise.reject(err);
});


fire.request().then((res) => {
  console.log('请求正常');
  console.log(res);
})
  .catch((err) => {
    console.log('请求发送错误');
    console.log(err);
  });

其主要的原理在于 给 真正的请求 dispatchRequest 的前面增加 请求拦截器的执行,后面增加响应拦截器的执行,注意,这里按照axios的原理还原,所以,请求拦截器的执行顺序按照后添加先执行的方式来做。

shift操作把数据最前面的元素拿出来,然后在unshift到一个数字,所以顺序就调转过来了。

最重要的是利用了 promise.then(onFulfilled[, onRejected])

代码语言:javascript
复制
promise.then(onFulfilled[, onRejected]);

promise.then(value => {
  // fulfillment
}, reason => {
  // rejection
});

这里的实现

代码语言:javascript
复制
while (chain.length > 0) {
        promise = promise.then(chain.shift(), chain.shift());
 }

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Axios 是什么?
  • 拦截器的原理:
    • 下面这个是完全参考axios写的一个请求和响应拦截器的简化版本
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档