说一下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;