JavaScript - 相对实用的Axios二次封装

0 阅读1分钟

1. 为什么要对Axios进行二次封装?

如果不对Axios进行二次封装,可以想象到每次调用Axios都需要对其重复的进行配置。

并且封装Axios,也能够使得每次请求的入口相同,更加便于管理。

2. 如何对Axios进行二次封装

首先我们需要构建出一个axios实例用于发送请求,以及需要绑定一些方法,使得每次请求的入口都是这些方法。其次,错误处理和令牌数据携带需要在Axios拦截器进行构造。

构建HTTP请求类:

import axios from "axios";
import baseConfig from "./baseConfig";
import { InterceptorController } from "./InterceptorController";
class HTTP {
  constructor(extraConfig) {
   const mergeConfig = {...baseConfig,...extraConfig};
   this.ins = axios.create({
    ...mergeConfig
   })
   
   /** 创建拦截器实例 */
   const interceptorController = new InterceptorController(this.ins)
   interceptorController.addRequestInterceptor.apply(this);
   interceptorController.addResponseInterceptor.apply(this);
  }
  
  /** 通用的请求方法 */
  async request(url, config) {
   try {
    return await this.ins({ url, ...config, });
   } catch (error) {
    throw error.response ? error.response.data : error;
   }
  }
  
  post(url, data, config){
   return this.request(url, { ...config, data, method: 'POST' });
  }
  
  get(url, config) {
   return this.request(url, { ...config, method: 'GET' });
  }
}

构建Axios拦截器:

import qs from 'qs';
import { responseCodeMap } from 'responseCodeMap.js';
/** axios拦截控制器 */
export class InterceptorController {
  /**
   * @param ins - axios实例
   */
  constructor(ins) {
   this.ins = ins;
   /** 用于超时重试计数 */
   this.retryCount = 1;
  };
  
  addRequestInterceptor() {
   this.ins.interceptors.request.use((config) => {
    loading();
    
    /** 携带token,假设token存入了store中 */
    const token = store.commit('token');
    if(store.commit('getToken')){
     config.headers.token = token;
    }else{
     redirectTo('login');
    }
    
    config.data = qs.stringify(config.data);
   },(error) => {
    closeLoading();
    
    /** 重定向到错误页面 */
    redirectTo('error' + error.response.status);
    
    return Promise.reject(error);
   });
  }
  
  addResponseInterceptor(){
   this.ins.interceptors.response.use((res) => {
    closeLoading();
    return res;
   },(error) => {
    closeLoading();
    /** 超时重发请求 */
    if(error.code === 'ECONNABORTED' && error.message.includes('timeout')){
     const config = error.config;
     
     if(this.retryCount <= 3){
      this.retryCount++;
      console.warn(`请求超时,第${this.retryCount - 1}次重试`);
      return new Promise(resolve => {
       setTimeout(() => {
        resolve(this.ins(config));
       }, 1000);
      });
     }else{
      console.error('请求重试失败,已达最大重试次数');
      this.retryCount = 1;
      $message.error('网络请求超时,请稍后重试');
     }
    }
   })
  }
}