Axios封装, 让你的请求更加优雅

封装 axios 需要具备以下几个功能:

  1. 请求超时时间设置
  2. 根据项目环境设置请求路径
  3. 请求拦截器:自动添加 Token
  4. 响应拦截器:处理响应状态码或数据格式化
  5. 请求队列实现 loading 效果
  6. 取消请求功能:页面切换时取消未完成的请求

下面是一个完整的 axios 封装示例,包含这些功能:

1. 安装依赖

npm install axios nprogress

nprogress 是一个用于显示加载进度条的库,可以帮助实现 loading 效果。

2. 封装 axios

js 复制代码
// 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;

3. 使用导航守卫取消未完成请求

在页面切换时,通过 Vue Router 的导航守卫取消未完成的请求。

js 复制代码
// 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;

4. 在组件中使用 axios 封装

在 Vue 组件中使用封装的 axios

vue 复制代码
<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>

5. 效果解析

  1. 请求超时 :在 axios 实例中通过 timeout: 5000 设置了 5 秒的请求超时。
  2. 根据环境设置请求路径 :使用 process.env.NODE_ENV 判断当前环境,并设置 baseURL
  3. 请求拦截:自动添加 Token :每次请求会从 localStorage 中获取 Token 并添加到 Authorization 请求头中。
  4. 响应拦截:处理状态码与格式化数据:统一处理了响应的状态码,如果不是 200,会抛出错误。
  5. 请求队列与 loading 效果 :使用 nprogress 显示加载进度条,且通过请求队列管理,防止重复请求。
  6. 取消请求功能 :在每次请求时生成一个取消 token,并在页面切换时通过导航守卫取消未完成的请求。

通过这种封装,你可以有效管理请求的全生命周期,并确保在项目中对 HTTP 请求的处理变得更高效、可维护。

相关推荐
jessezappy6 分钟前
jQuery-Word-Export 使用记录及完整修正文件下载 jquery.wordexport.js
前端·word·jquery·filesaver·word-export
旧林84333 分钟前
第八章 利用CSS制作导航菜单
前端·css
yngsqq1 小时前
c#使用高版本8.0步骤
java·前端·c#
Myli_ing1 小时前
考研倒计时-配色+1
前端·javascript·考研
余道各努力,千里自同风1 小时前
前端 vue 如何区分开发环境
前端·javascript·vue.js
PandaCave1 小时前
vue工程运行、构建、引用环境参数学习记录
javascript·vue.js·学习
软件小伟2 小时前
Vue3+element-plus 实现中英文切换(Vue-i18n组件的使用)
前端·javascript·vue.js
醉の虾2 小时前
Vue3 使用v-for 渲染列表数据后更新
前端·javascript·vue.js
张小小大智慧2 小时前
TypeScript 的发展与基本语法
前端·javascript·typescript
hummhumm2 小时前
第 22 章 - Go语言 测试与基准测试
java·大数据·开发语言·前端·python·golang·log4j