项目里的请求若不收敛,Token 注入、401 处理、错误提示会在每个页面重复写。用一个 axios 实例统一拦截,后端返回结构变化时只需改一处。

实现思路

axios.create 生成实例并配置 baseURL 与超时;请求拦截器读取本地 Token 写入 Authorization 头;响应拦截器先判业务码 code,为 401 时清登录态跳登录页,其它非 0 码统一弹错误提示。

完整代码

// src/utils/request.js
import axios from "axios";
import { ElMessage } from "element-plus";

const request = axios.create({
    baseURL: "/api",
    timeout: 10000
});

// 请求拦截:注入 Token
request.interceptors.request.use((config) => {
    const token = localStorage.getItem("token");
    if (token) {
        config.headers.Authorization = "Bearer " + token;
    }
    return config;
});

// 响应拦截:统一业务码与错误提示
request.interceptors.response.use(
    (response) => {
        const res = response.data;
        // 兼容后端 { code, data, msg } 结构
        if (res.code !== undefined && res.code !== 0) {
            if (res.code === 401) {
                localStorage.removeItem("token");
                location.href = "/login";
                return Promise.reject(new Error("登录已过期"));
            }
            ElMessage.error(res.msg || "请求失败");
            return Promise.reject(new Error(res.msg));
        }
        return res.data !== undefined ? res.data : res;
    },
    (error) => {
        ElMessage.error(error.message || "网络异常");
        return Promise.reject(error);
    }
);

export default request;

页面调用

import request from "@/utils/request"; 然后 request.get("/user/list", { params: { page: 1 } }) 拿到的直接是业务 data,调用处不再重复判断 code,代码大幅瘦身。

注意

  • 登录页等少数场景需要跳过拦截时,可在 config 里加自定义标记并在响应拦截分支判断;
  • 下载文件、上传进度等需要拿到原生响应的请求,可单独用 axios 原生方法;
  • Token 过期在并发请求时可能触发多次跳转,建议加跳转锁。

小结

统一请求层是前端工程化的第一道关卡,拦截器把鉴权、错误、重试等横切关注点集中管理,接口代码保持纯粹。