你还不会axios二次封装吗快进来看看吧(小白进)

94 阅读4分钟

说一下axio关于二次封装

今天说三个,分别是取消重复请求,然后是请求请求失败二次请求,还有一个是关于token失效之后涉及到的关于权限方面的问题; 然后话不多说,上代码:

1.请求失败二次请求

axios 利用interceptors(拦截器)完美解决自动重试问题。

Axios 是一个基于 Promise 的 HTTP 客户端,而 HTTP 协议是基于请求和响应:

所以 Axios 提供了 请求拦截器和响应拦截器 来分别处理请求和响应,它们的作用如下:

请求拦截器:该类拦截器的作用是在请求发送前统一执行某些操作,比如在请求头中添加 token 字段。

响应拦截器:该类拦截器的作用是在接收到服务器响应后统一执行某些操作,比如发现响应状态码为 401 时,自动跳转到登录页。 import axios from 'axios'

// 重试次数,共请求2次

    axios.defaults.retry = 1

// 请求的间隙

    axios.defaults.retryDelay = 1000

响应器配置

axios.interceptors.response.use(
	function (response) {
		// 2xx 范围内的状态码都会触发该函数。
		// 对响应数据做点什么
		console.log(response.data.status);
		if (response.data.status === 410000) {
			router.replace({
				path: "/login",
				query: { redirect: router.currentRoute.fullPath }, //登录成功后跳入浏览的当前页面
			});
		}
		return response;
	},
	function axiosRetryInterceptor(err) {
		var config = err.config;
		// 如果配置不存在或未设置重试选项,则拒绝
		if (!config || !config.retry) return Promise.reject(err);

		// 设置变量以跟踪重试次数
		config.__retryCount = config.__retryCount || 0;

		// 判断是否超过总重试次数
		if (config.__retryCount >= config.retry) {
			// 返回错误并退出自动重试
			return Promise.reject(err);
		}

		// 增加重试次数
		config.__retryCount += 1;

		//打印当前重试次数
		console.log(config.url + " 自动重试第" + config.__retryCount + "次");

		// 创建新的Promise
		var backoff = new Promise(function (resolve) {
			setTimeout(function () {
				resolve();
			}, config.retryDelay || 1);
		});

		// 返回重试请求
		return backoff.then(function () {
			return axios(config);
		});
	}
);

测试接口

axios.get('https://www.google.com', {
        retry: 5,
        retryDelay: 1000,
        timeout: 6000
    })
    .then(res=> {
        console.log('success', res.data);
    })
    .catch(err=> {
        console.log('failed', err);
    })

2.token失效处理

token关系着一些权限验证的问题,他也是至关重要的,所以有的token他会失效,尤其是涉及到权限方面的问题时,所以说,我们在axios二次封装的时候也要应该设置token失效问题。 它的原理就是当接口的返回值为200的时候证明一切正常,如果不是200的话,证明token失效,要求我们跳转到登录页进行权限认证,上代码:

instance.interceptors.response.use(
	function (response) {
		// 2xx 范围内的状态码都会触发该函数。
		// 对响应数据做点什么
		if (response.data.status === 410000) {
			router.replace({
				path: "/login",
				query: { redirect: router.currentRoute.fullPath }, //登录成功后跳入浏览的当前页面
			});
		}
		return response;
	},
	
);

这段代码是添加在

3.取消重复请求

Axios 是一个基于 Promise 的 HTTP 客户端,同时支持浏览器和 Node.js 环境。它是一个优秀的 HTTP 客户端,被广泛地应用在大量的 Web 项目中。对于浏览器环境来说,Axios 底层是利用 XMLHttpRequest 对象来发起 HTTP 请求。如果要取消请求的话,我们可以通过调用 XMLHttpRequest 对象上的 abort 方法来取消请求:

在外面定义条件

const pending = [];
const removePending = (config) => {
	let pendingIndex = pending.findIndex((v) => {
		if (
			config.url === v.url &&
			config.method === v.method &&
			JSON.stringify(config.params) === JSON.stringify(v.params) &&
			JSON.stringify(config.body) === JSON.stringify(v.body)
		) {
			v.controller.abort();
			return true;
		}
		return false;
	});
	if (pendingIndex >= 0) {
		pending.splice(pendingIndex, 1);
	}
};

然后就在这个axios.interceptors.request.use下的function (config) 中调用

		removePending(config);
		const controller = new AbortController();
		config.signal = controller.signal;
		config.controller = controller;
		pending.push({ ...config });

这样我们的axios取消重复请求就完成了

axios二次封装就到此为止啦,最后双手奉我的代码:
import axios from "axios";
import qs from "qs";
import router from "../router/index";
import { Toast } from "vant";
const axios = axios.create({
	baseURL: "http://47.93.101.203/api",
	timeout: 5000000,
});

const pending = [];
const removePending = (config) => {
	let pendingIndex = pending.findIndex((v) => {
		if (
			config.url === v.url &&
			config.method === v.method &&
			JSON.stringify(config.params) === JSON.stringify(v.params) &&
			JSON.stringify(config.body) === JSON.stringify(v.body)
		) {
			v.controller.abort();
			return true;
		}
		return false;
	});
	if (pendingIndex >= 0) {
		pending.splice(pendingIndex, 1);
	}
};
// 重试次数,共请求2次
axios.defaults.retry = 1;
// 请求的间隙
axios.defaults.retryDelay = 1000;
axios.interceptors.request.use(
	function (config) {
		// 在发送请求之前做些什么
		removePending(config);
		const controller = new AbortController();
		config.signal = controller.signal;
		config.controller = controller;
		pending.push({ ...config });
		let token = localStorage.getItem("token");
		config.headers = {
			...config.headers,
			"Authori-zation": `Bearer ${token}`,
		};
		return config;
	},
	function (error) {
		// 对请求错误做些什么
		return Promise.reject(error);
	}
);

// 添加响应拦截器
axios.interceptors.response.use(
	function (response) {
		// 2xx 范围内的状态码都会触发该函数。
		// 对响应数据做点什么
		console.log(response.data.status);
		if (response.data.status === 410000) {
			router.replace({
				path: "/login",
				query: { redirect: router.currentRoute.fullPath }, //登录成功后跳入浏览的当前页面
			});
		}
		return response;
	},
	function axiosRetryInterceptor(err) {
		var config = err.config;
		// 如果配置不存在或未设置重试选项,则拒绝
		if (!config || !config.retry) return Promise.reject(err);

		// 设置变量以跟踪重试次数
		config.__retryCount = config.__retryCount || 0;

		// 判断是否超过总重试次数
		if (config.__retryCount >= config.retry) {
			// 返回错误并退出自动重试
			return Promise.reject(err);
		}

		// 增加重试次数
		config.__retryCount += 1;

		//打印当前重试次数
		console.log(config.url + " 自动重试第" + config.__retryCount + "次");

		// 创建新的Promise
		var backoff = new Promise(function (resolve) {
			setTimeout(function () {
				resolve();
			}, config.retryDelay || 1);
		});

		// 返回重试请求
		return backoff.then(function () {
			return axios(config);
		});
	}
);
export default axios;