安装依赖
nprogress 是一个用于显示加载进度条的库,可以帮助实现 loading 效果。
npm install axios nprogress
封装 axios
src/utils/request.js
import axios from 'axios';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
// 设置取消请求的 token
const CancelToken = axios.CancelToken;
let pendingRequests = new Map(); // 用于存储请求队列
// 添加请求到队列
const addRequestToQueue = (config) => {
const requestKey = `${config.method}:${config.url}`;
config.cancelToken = new CancelToken((cancel) => {
if (!pendingRequests.has(requestKey)) {
pendingRequests.set(requestKey, cancel);
}
});
};
// 移除队列中的请求
const removeRequestFromQueue = (config) => {
const requestKey = `${config.method}:${config.url}`;
if (pendingRequests.has(requestKey)) {
const cancel = pendingRequests.get(requestKey);
cancel(requestKey);
pendingRequests.delete(requestKey);
}
};
// 清空请求队列(用于页面切换时取消请求)
export const clearRequestQueue = () => {
pendingRequests.forEach((cancel, key) => {
cancel(key);
});
pendingRequests.clear();
};
// 根据环境变量设置基础URL
const baseURL = process.env.NODE_ENV === 'production' ? 'https://api.production.com' : 'https://api.development.com';
// 创建 axios 实例
const service = axios.create({
baseURL: baseURL,
timeout: 5000, // 超时时间
headers: {
'Content-Type': 'application/json',
}
});
// 请求拦截器
service.interceptors.request.use(
(config) => {
// 启动进度条
NProgress.start();
// 自动添加 Token 到请求头
const token = localStorage.getItem('token');
if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
}
// 添加请求到队列,防止重复请求
removeRequestFromQueue(config);
addRequestToQueue(config);
return config;
},
(error) => {
// 关闭进度条
NProgress.done();
return Promise.reject(error);
}
);
// 响应拦截器
service.interceptors.response.use(
(response) => {
// 关闭进度条
NProgress.done();
// 请求成功后移除队列中的该请求
removeRequestFromQueue(response.config);
const res = response.data;
// 自定义状态码处理
if (res.code !== 200) {
// 错误处理
console.error('Error:', res.message);
// 比如处理 token 过期
if (res.code === 401) {
console.error('Token expired, redirecting to login...');
// 可以执行登出操作,或跳转到登录页面
}
return Promise.reject(new Error(res.message || 'Error'));
} else {
return res; // 返回处理过的数据
}
},
(error) => {
// 关闭进度条
NProgress.done();
// 请求失败时清除队列中的该请求
removeRequestFromQueue(error.config || {});
return Promise.reject(error);
}
);
export default service;
使用导航守卫取消未完成请求
在页面切换时,通过 Vue Router 的导航守卫取消未完成的请求。 src/router/index.js
import Vue from 'vue';
import Router from 'vue-router';
import { clearRequestQueue } from '@/utils/request'; // 引入清除请求队列的函数
Vue.use(Router);
const router = new Router({
routes: [
// 定义你的路由
]
});
router.beforeEach((to, from, next) => {
// 页面切换前取消所有未完成的请求
clearRequestQueue();
next();
});
export default router;
在组件中使用 axios 封装
在 Vue 组件中使用封装的 axios
<template>
<div>
<h1>{{ data }}</h1>
</div>
</template>
<script>
import service from '@/utils/request';
export default {
data() {
return {
data: null,
};
},
async created() {
try {
const response = await service.get('/some-endpoint');
this.data = response.data;
} catch (error) {
console.error('Error fetching data:', error);
}
}
};
</script>