axios 基本使用及封装

107 阅读2分钟

目标

  1. 设置默认配置
    • 基础域名:baseURL
    • 超时时间:timeout
  2. 请求拦截 体现在headers设置
    • token
    • expireTimes
    • Content-Type
    • X-Requested-With
  3. 响应拦截
    • 响应成功后错误码上报
    • 响应失败后,提示超时 && 请求重发
  4. 封装get和post请求
  5. 使用例子

axios.js

import axios from 'axios';
import { message } from 'antd';
import { sendReport, retryRequest } from './axiosRequestTools';

const SUCCESS_CODE = 0;
const NO_AUTH_CODE = 40001;
const ERR_MSG = '请求失败,请稍后重试!';

const instance = axios.create({
  timeout: 30000,
  withCredentials: true,
});

instance.interceptors.request.use((config) => {
  const token = document.getElementById('token');
  const expire_times = document.getElementById('expire_times');
  if (token && token.value) {
    config.headers['token'] = token.value;
  }
  if (expire_times && expire_times.value) {
    config.headers['expireTimes'] = expire_times.value;
  }
  config.headers['Content-Type'] =
    'application/x-www-form-urlencoded; charset=UTF-8';
  config.headers['X-Requested-With'] = 'XMLHttpRequest';
  return config;
});

instance.interceptors.response.use(
  (response) => {
    const { errno, data, msg } = response.data;
    if (errno === SUCCESS_CODE) {
      return data;
    } else {
      //根据code决定是否上报打点
      //sendReport(errno, instance);
      if (errno === NO_AUTH_CODE) {
        const isProd = window.location.origin.indexOf('//soft.cn') > -1;
        const url = isProd ? 'https://e.cn/' : 'https://trunk.e.cn/';
        window.location.href = url;
      }
      return Promise.reject(msg);
    }
  },
  (error) => {
    if (error.response) {
      // 请求成功发出且服务器也响应了状态码,但状态代码超出了 2xx 的范围
      if (error.response?.status >= 500) {
        return Promise.reject(ERR_MSG);
      }
      return Promise.reject(error.response?.statusText);
    }
    //错误重试(可选)
    //return retryRequest(error, instance)
    // 发送请求时出了点问题
    return Promise.reject(error.message);
  },
);

/** get方法支持传入泛型表示promise resolve后的类型 */
export const get = <Data>({
  url,
  data = {},
  showError = true,
}: {
  url: string;
  data?: unknown;
  showError?: boolean;
}): Promise<Data> => {
  return instance.get<Data>(url, { params: data }).catch((error) => {
    if (showError) {
      message.error(error);
    }
    return Promise.reject(error);
  }) as Promise<Data>;
};

/** post方法支持传入泛型表示promise resolve后的类型 */
export const post = <Data>({
  url,
  data = {},
  showError = true,
}: {
  url: string;
  data?: unknown;
  showError?: boolean;
}): Promise<Data> => {
  return instance.post(url, data).catch((error) => {
    if (showError) {
      message.error(error);
    }
    return Promise.reject(error);
  }) as Promise<Data>;
};

axiosRequestTools.js

export const sendReport = (code, axiosInstance) => {
    const data = {
       msg: `发生${code}请求错误`,
       url,
       file: window.loacation.href,
       params
     }
    axiosInstance.post('/ajax/sendodin', qs.stringify({ errData: JSON.stringify(data) }))
}
// 实现 请求错误时重新发送接口
export const retryRequest = (err, axiosInstance) => {
  let config = err.config
  // config.retry 具体接口配置的重发次数
  if (!config || !config.retry) return Promise.reject(err)

  // 设置用于记录重试计数的变量 默认为0
  config.__retryCount = config.__retryCount || 0

  // 判断是否超过了重试次数
  if (config.__retryCount >= config.retry) {
    return Promise.reject(err)
  }
  // 重试次数
  config.__retryCount += 1
  //打印当前重试次数
  console.log(config.url + ' 自动重试第' + config.__retryCount + '次')

  // 延时处理
  const backoff = new Promise(function (resolve) {
    setTimeout(function () {
      resolve()
    }, config.retryDelay || 400)
  })
  // 重新发起axios请求
  return backoff.then(function () {
    return axiosInstance(config)
  })
}

使用示例 service.js

import { get,post } from '@/utils/axios';

export const getStatusData = () => {
  return get({
    url: '/api/getStatus',
  });
};
export const postData = (data) => {
  return post({
    url: '/goapi/soft/add',
    data,
    showError: false,
  });
};