Axios
是vue项目
中使用最多的一个第三方开源免费的HTTP库
,最大的特点在于可以同时兼容浏览器端和NodeJS
服务端。底层通过判定不同的运行环境来自动提供不同的适配器,在浏览器端通过原生的XHR
对象来发送请求,而在NodeJS
服务端则通过内置的http模块
来发送请求。
1、基础示例
// 安装 axios
npm install --save axios;
// 导入 axios
import axios from 'axios';
// 创建 axios 实例
const instance = axios.create({
baseURL: 'https://www.some-domain.com/path/to/example',
timeout: 30000,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
// 设置 axios 实例默认配置
instance.defaults.headers.common['Authorization'] = '';
instance.defaults.headers.post['Content-Type'] = 'application/json; charset=UTF-8';
// 自定义请求拦截器
instance.interceptors.request.use(config => {
const token = window.localStorage.getItem('token');
token && (config.headers['Authorization'] = token);
return config;
}, error => Promise.reject(error));
// 自定义响应拦截器
instance.interceptors.response.use(response => {
if (response.status === 200) {
return Promise.resolve(response.data);
}
return Promise.reject(response);
}, error => Promise.reject(error));
2、结合Axios
提供的CancelToken
构造函数来创建一个简单的post请求
const CancelToken = axios.CancelToken;
let cancel;
instance.post('/api/user/123', {
name: 'new name',
phone: 'new phone',
}, {
// CancelToken 构造函数接收一个 executor 函数参数,并且该函数接收一个取消函数 c 用于取消该次请求
cancelToken: new CancelToken(function executor(c) {
// 将取消函数赋值到外部变量,方便从外部取消请求
cancel = c;
}),
});
// 手动取消请求
cancel();
3、为了避免在每个请求中都需要手动去实例化CancelToken
,我们可以巧妙利用request拦截器
来整合这部分的逻辑,实现逻辑复用
3.1、首先将缓存逻辑拆分到一个单独的文件中:
// cacheUtils.js
export const CacheUtils = {
// 存储请求接口地址以及请求体和取消函数之间的映射关系
cache: {
},
// 根据提供的键名 key 取消对应的请求,若未提供则取消全部请求
clearCache: function (key) {
if (key) {
const cancel = this.cache[key];
if (cancel && typeof cancel === 'function') {
cancel();
delete this.cache[key];
}
return;
}
Object.keys(this.cache).forEach(cacheKey => {
const cancel = this.cache[cacheKey];
cancel();
delete this.cache[cacheKey];
});
},
};
3.2、接下来将其应用到请求拦截器和响应拦截器中:
import qs from 'qs';
import {
CacheUtils } from './cacheUtils.js';
// 自定义请求拦截器
instance.interceptors.request.use(config => {
let cacheKey = config.url;
const token = window.localStorage.getItem('token');
token && (config.headers['Authorization'] = token);
const method = config.method.toLowerCase();
if (method === 'get' && config.params && typeof config.params === 'object') {
cacheKey += qs.stringify(config.params, {
addQueryPrefix: true });
}
if (['post', 'put', 'patch'].includes(method) && config.data && typeof config.data === 'object') {
config.data = qs.stringify(config.data);
cacheKey += `_${
qs.stringify(config.data, {
arrayFormat: 'brackets' })}`;
}
// 每次发送请求之前将上一个未完成的相同请求进行中断
CacheUtils.cache[cacheKey] && CacheUtils.clearCache(cacheKey);
// 将当前请求所对应的取消函数存入缓存
config.cancelToken = new axios.CancelToken(function executor(c) {
CacheUtils.cache[cacheKey] = c;
});
// 临时保存 cacheKey,用于在响应拦截器中清除缓存
config.cacheKey = cacheKey;
return config;
}, error => Promise.reject(error));
// 自定义响应拦截器
instance.interceptors.response.use(response => {
// 响应接收之后清除缓存
const cacheKey = response.config.cacheKey;
delete CacheUtils.cache[cacheKey];
if (response.status === 200) {
return Promise.resolve(response.data);
}
return Promise.reject(response);
}, error => {
// 响应异常清除缓存
if (error.config) {
const cacheKey = error.config.cacheKey;
delete CacheUtils.cache[cacheKey];
}
return Promise.reject(error);
});
3.3、同样提供CacheUtils.clearCache
函数来应对需要手动清除未完成请求的应用场景,使用方式:
// 网页卸载前清除缓存
window.addEventListener('beforeunload', () => CacheUtils.clearCache(), false);
// Vue 中路由跳转前清除缓存
router.beforeEach((to, from, next) => {
CacheUtils.clearCache(); next(); });