axios封装以及详细用法axios请求拦截响应拦截请求重试请求终止

axios官方文档

说明:这里是在老项目中继续封装的,如果新项目可以将index.ts中的响应拦截异常处理和request中的异常处理合并在一起,无感刷新token,由于提供了思路,一共参考

index.ts

axios的基本封装(请求拦截、响应拦截)

import { message } from 'ant-design-vue';
import axios from 'axios';
import router from '../router';
import { globalData } from '../setting/global';
import { ref } from 'vue';
const host = ref('localhost');
const serverUrl = ref('localhost');

//这里是electron中的本地存储,如果不知道可以理解为localstory
const Store = require('electron-store');

const store = new Store();

const serverAddressIp = store.get('serverAddressIp'); //是否首次输入服务器IP
if (serverAddressIp) {
  host.value = serverAddressIp;
}

serverUrl.value = 'http://' + host.value + ':8102';

//用于更新用户切换链接的服务器IP
export function updateServer(address: string) {
  host.value = address;
  serverUrl.value = 'http://' + host.value + ':8102';
}

export const serverAddress = () => serverUrl.value + '/';

export const serverIp = () => host.value;

axios.defaults.withCredentials = true;

let config = {
  baseURL: serverUrl.value ? serverUrl.value : globalData.apiUrl,
  withCredentials: true,
  Headers: {
    'Content-Type': 'application/json',
  },
  timeout: 10 * 60 * 1000,
};

const http = axios.create(config);

http.interceptors.request.use(
  (config: any) => {
    const token = sessionStorage.getItem('TOKEN');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    config.headers['Content-Type'] = 'application/json';
    config.url = serverUrl.value + config.url;
    return config;
  },
  (error) => {
    // Do something with request error
    return Promise.reject(error);
  },
);

// Add a response interceptor
http.interceptors.response.use(
  (response) => {
    // Do something with response data
    return response.data;
  },
  (error) => {
    if (error.message.includes('timeout')) {
      return Promise.reject('timeout');
      message.error('任务执行时间过长');
    } else if (error.response?.status === 401) {
      message.error('身份已失效,请重新登录!');
      router.push('/login');
    } else if (error.response?.status === 405) {
      message.error('请求方式错误');
    } else if (error.response?.status === 500) {
      message.error('服务器内部错误');
    } else if (error.response?.status === 400) {
      //下面就不改了,项目中改动太多
      console.log('请求错误');
    } else if (error.response?.status === 403) {
      console.log('拒绝访问');
    } else if (error.response?.status === 404) {
      console.log('请求地址出错');
    } else if (error.response?.status === 422) {
      console.log('请求参数错误');
    } else if (error.response?.status === 501) {
      console.log('服务未实现');
    } else if (error.response?.status === 502) {
      console.log('网关错误');
    } else if (error.response?.status === 503) {
      console.log('服务不可用');
    } else if (error.response?.status === 504) {
      console.log('网关超时');
    } else if (error.response?.status === 505) {
      console.log('HTTP版本不受支持');
    }
    // Do something with response error
    return Promise.reject(error.response);
  },
);

export default http;

request.ts

在index.ts的基础上增加请求重试、请求终止(也可以实现无感刷新)

import http from './index';

const timeout = 60000; // 超时时间 官方默认3000      index.ts 设置了600000ms
let retryTime = 1; // 重试次数
let configTemp: any = {};

// 执行请求的方法
function request(config: any) {
  configTemp = config;
  return http({
    ...config,
    // timeout,
  })
    .then((res) => {
      return Promise.resolve(res);
    })
    .catch((error) => {
      // 先解释一下,由于这里是在老项目中封装的,为了兼容之前写的项目不做调整,就在这里异常处理,其实index.ts中的catch完全可以放在这里处理
      console.log(error);
      if (error.includes('timeout'))
        if (retryTime >= 3) {
          // 重试次数超过了限制
        } else {
          retryTime++;
          request(configTemp);
        }
      // if(code == 401)  如果token失效,想做无感刷新,在这里重新请求一次获取token,让token失效前正在请求还没有请求的接口保存在一个数组里面,等到token更新好,遍历数组将没有请求成功的接口继续请求,这里就可以实现无感刷新了
      return Promise.reject(error);
      // 使用 Promise.reject 手动抛出异常,让 Promise.all 并发请求的方法中的 catch 捕获该异常,从而实现重试机制
      // return Promise.reject(error);
    });
}

// 取消请求 具体参看官网
// const controller = new AbortController();
// const cancelAxios = () => {
//   controller.abort();
// };

/**
 * 封装 get 请求方法
 * @param url
 * @param params 对象
 * @param other 其他参数,(上传下载文件流,请求终止等参数) 比如  { responseType: 'blob' }  {   signal: controller.signal }
 * @returns
 */
export function get(url: string, params = {}, other?: any) {
  return request({
    url,
    params,
    method: 'get',
    ...other,
  });
}

/**
 * 封装 post 请求方法
 * @param url
 * @param params 对象
 * @param other 其他参数,(上传下载文件流,请求终止等参数) 比如  { responseType: 'blob' }  {   signal: controller.signal }
 * @returns
 */
export function post(url: string, data = {}, other?: any) {
  return request({
    url,
    data,
    method: 'post',
    ...other,
  });
}

// 封装 put 请求方法
export function put(url: string, data = {}) {
  return request({
    url,
    data,
    method: 'put',
  });
}

// 封装 delete 请求方法
export function del(url: string, params = {}) {
  return request({
    url,
    params,
    method: 'delete',
  });
}

index.ts 和 request.ts 中的方法使用

import http from '../../index';
import { formatQuery } from '../../../libs/utils/format';
import { get, post, put, del } from '../../request';

const prefix: string = '/meta/tasks';


/**
 * 将对象转化为URL的查询字符串
 * @param q 查询对象
 * @returns URL的查询字符串
 */

export const formatQuery = (q: any) => {
  let query = '';
  Object.keys(q).forEach((key) => {
    if (q[key] !== '' && q[key] !== undefined) {
      query += `${key}=${q[key]}&`;
    }
  });
  return query.substring(0, query.length - 1);
};

export const getTasks = (
  status: string | undefined,
  page: number,
  pageSize: number,
  signal: any,
  sorterName?: string,
  sorterType?: string,
  sixteen?: string,
  generation?: string,
  name?: string,
) => {
  return http.get(
    `${prefix}?${formatQuery({
      query: status !== '' && status !== undefined ? `status:${status}` : '',
      page,
      pageSize,
      sorterName,
      sorterType,
      sixteen,
      generation,
      name,
    })}`,
  );
};

export const getTasks2 = (
  status: string | undefined,
  page: number,
  pageSize: number,
  signal: any,
  sorterName?: string,
  sorterType?: string,
  sixteen?: string,
  generation?: string,
  name?: string,
) => {
  let params = {
    query: status !== '' && status !== undefined ? `status:${status}` : '',
    page,
    pageSize,
    sorterName,
    sorterType,
    sixteen,
    generation,
    name,
  };
  return get(prefix, params, { signal });
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜空孤狼啸

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值