此次进行简单的封装,所以暂时没有考虑取消重复请求、重复发送请求、请求缓存等情况!这里主要实现以下目的:
请求拦截器
发送请求之前运行一般会判断是否有token,如果token存在则在请求头加上这个token。服务端会判断我这个token是否过期。可以设置加载全局loading。等
响应拦截器
对服务端返回的数据进行处理,存储token,错误处理、登录、登录失效路由跳转、关闭全局loading等。
目录结构如下:

index.js代码如下
- /*
- * @Description:
- * @Version: 2.0
- * @Autor: Cookie
- * @Date: 2022-06-28 11:33:32
- * @LastEditors: Zhang
- * @LastEditTime: 2022-06-28 15:38:21
- */
- import serverConfig from "./config";
- import axios from 'axios'
- import qs from "qs";
- import { Message, Loading, MessageBox } from 'element-ui';
-
- // loading函数
- // 记录请求次数
- let needLoadingRequestCount = 0;
- let loading;
- function startLoading() {
- loading = Loading.service({
- lock: true,
- text: '加载中……',
- background: 'rgba(0, 0, 0, 0.5)',
- });
- }
- function endLoading() {
- // 延迟500ms,防止网速特快加载中画面一闪而过
- setTimeout(function () {
- if (loading) loading.close();
- }, 500);
- }
- // 打开loading
- function showFullScreenLoading() {
- if (needLoadingRequestCount === 0) {
- startLoading();
- }
- needLoadingRequestCount++;
- }
- // 关闭loading
- function tryHideFullScreenLoading() {
- if (needLoadingRequestCount <= 0) return;
- needLoadingRequestCount--;
- if (needLoadingRequestCount === 0) {
- endLoading();
- }
- }
-
- // 创建实例
- const serviceAxios = axios.create({
- baseURL: serverConfig.baseURL, // 基础请求地址
- timeout: 10000, // 请求超时设置
- // withCredentials: false, // 跨域请求是否需要携带 cookie
- });
-
- // 添加请求拦截器
- serviceAxios.interceptors.request.use(
- config => {
- // 在发送请求之前做些什么
- // 打开loading
- showFullScreenLoading();
- // 如果开启 token 认证
- if (serverConfig.useTokenAuthorization) {
- config.headers["Authorization"] = JSON.parse(localStorage.getItem("token")); // 请求头携带 token
- }
- // axios.defaults.headers.common['Authorization'] = localStorage.getItem("token")
- // 设置请求头
- if (!config.headers["content-type"]) { // 如果没有设置请求头
- if (config.method === 'post') {
- config.headers["content-type"] = "application/x-www-form-urlencoded"; // post 请求
- config.data = qs.stringify(config.data); // 序列化,比如表单数据
- } else {
- config.headers["content-type"] = "application/json"; // 默认类型(get)
- // axios.defaults.headers.post['Content-Type'] = 'application/json';
-
- }
- }
- console.log("请求配置", config);
- return config;
- },
- error => {
- // 对请求错误做些什么
- // 关闭loading
- tryHideFullScreenLoading();
- return Promise.reject(error);
- }
- );
-
- // 添加响应拦截器
- serviceAxios.interceptors.response.use(
- res => {
- console.log('响应', res)
- // 关闭loading
- tryHideFullScreenLoading();
- let data = res.data
- if (!res.success) {
- // B002:Token 过期了;
- if (res.code === 'B002') {
- // 最后一次出弹框
- if (needLoadingRequestCount === 0) {
- MessageBox.confirm(
- `你已被登出,可以取消继续留在该页面,
- 或者重新登录, 确定登出`,
- {
- confirmButtonText: '重新登录',
- cancelButtonText: '取消',
- type: 'warning',
- },
- ).then(() => {
- // 返回登录页
- // ...做些事情
- // 为了重新实例化vue-router对象 避免bug
- location.reload();
- });
- }
- } else {
- Message({
- message: res.msg,
- type: 'error',
- });
- }
- }
- // 对响应数据做点什么
- return data;
- },
- error => {
- console.log('响应fail', error)
- // 对响应错误做点什么
- let message = "";
- if (error && error.response) {
- switch (error.response.status) {
- case 302:
- message = "接口重定向了!";
- break;
- case 400:
- message = "参数不正确!";
- break;
- case 401:
- message = "您未登录,或者登录已经超时,请先登录!";
- break;
- case 403:
- message = "您没有权限操作!";
- break;
- case 404:
- message = `请求地址出错: ${error.response.config.url}`;
- break;
- case 408:
- message = "请求超时!";
- break;
- case 409:
- message = "系统已存在相同数据!";
- break;
- case 500:
- message = "服务器内部错误!";
- break;
- case 501:
- message = "服务未实现!";
- break;
- case 502:
- message = "网关错误!";
- break;
- case 503:
- message = "服务不可用!";
- break;
- case 504:
- message = "服务暂时无法访问,请稍后再试!";
- break;
- case 505:
- message = "HTTP 版本不受支持!";
- break;
- default:
- message = "异常问题,请联系管理员!";
- break;
- }
- }
- return Promise.reject(message);
- }
- );
- console.log(serviceAxios)
-
- export default serviceAxios; //导出实例
config/index.js代码如下:
- const serverConfig = {
- baseURL: 'url', // 请求基础地址,可根据环境自定义
- useTokenAuthorization: true, // 是否开启 token 认证
- }
-
- export default serverConfig
api/user.js
- import serviceAxios from "../index";
-
-
- const login = (data) => {
- return serviceAxios({
- url: "/app/login",
- method: "post",
- data,
- });
- }
-
- const getUserInfo = (params) => {
- return serviceAxios({
- url: "/app/getSystemName",
- method: "get",
- params,
- });
- }
-
- export {
- login,
- getUserInfo
- }
vue文件中使用:
- mounted() {
- this.init();
- this.getInfo();
- },
- methods: {
- async init() {
- let params = {
- nickName: "admin",
- password: "6SJ2Lmmt0BKKiSWhQipe+Q=="
- };
- let res = await login(params);
- localStorage.setItem("token", JSON.stringify(res.data)); // 存放token
- console.log(res.data);
- },
- getInfo() {
- let params = {};
- getUserInfo(params).then(res => { // 也可以then的方式链式调用
- console.log(res);
- })
- }
- }
我们在此基础上可以根据业务场景做一些以下扩展建议: