返回

不再畏惧复杂请求—Axios最完整封装指南

前端

在 Vue.js 项目开发中,我们常常会使用 Axios 来处理网络请求。Axios 本身是一款功能强大的 HTTP 客户端库,但在实际应用中,为了更好地管理 API、提高代码可维护性和开发效率,我们通常需要对 Axios 进行一些封装。

本文就来探讨一下如何对 Axios 进行封装,使其更符合我们的项目需求。我们会涉及到 API 的集中管理,参数序列化,处理重复请求,以及加载状态和错误处理等方面。

API 的集中管理

当项目中有很多 API 接口时,如果把它们都散落在各个组件中,代码会变得难以维护。我们可以创建一个单独的文件来管理所有的 API 接口,例如 api.js

// api.js
const baseUrl = '/api'; // 可以根据实际情况设置

const API = {
  user: {
    login: `${baseUrl}/user/login`,
    getInfo: `${baseUrl}/user/info`
  },
  article: {
    getList: `${baseUrl}/article/list`,
    getDetail: `${baseUrl}/article/detail` 
  }
};

export default API;

然后在组件中,我们就可以通过引入 API 对象来调用相应的接口:

import API from '@/api';

// ...

this.$axios.get(API.article.getList).then(res => {
  // 处理数据
});

这样,API 接口的管理就变得更加集中和方便了。

参数序列化

有些 API 接口需要我们传递参数,而不同的接口对参数的格式要求可能不一样。我们可以利用 Axios 的拦截器来统一处理参数序列化。

// axios.js
import axios from 'axios';
import Qs from 'qs'; // 引入 qs 库,用于参数序列化

const instance = axios.create();

// 请求拦截器
instance.interceptors.request.use(config => {
  // 如果请求方法是 post 或 put,则将 data 参数序列化
  if (config.method === 'post' || config.method === 'put') {
    config.data = Qs.stringify(config.data);
  }
  return config;
}, error => {
  return Promise.reject(error);
});

export default instance;

这样,我们就可以在发送请求时,不用再手动对参数进行序列化了。

处理重复请求

有时候,用户可能会在短时间内多次点击同一个按钮,从而发送重复的请求。这不仅会浪费服务器资源,也可能导致一些不可预期的错误。我们可以通过维护一个请求队列来取消重复的请求。

// axios.js
// ...

let pendingRequests = {}; // 存储正在进行的请求

const removePendingRequest = config => {
  const requestKey = `${config.url}&${config.method}`;
  if (pendingRequests[requestKey]) {
    pendingRequests[requestKey]('取消重复请求'); // 取消请求
    delete pendingRequests[requestKey];
  }
};

// 请求拦截器
instance.interceptors.request.use(config => {
  removePendingRequest(config); // 检查是否存在重复请求
  config.cancelToken = new axios.CancelToken(c => {
    pendingRequests[`${config.url}&${config.method}`] = c;
  });
  return config;
}, error => {
  return Promise.reject(error);
});

// 响应拦截器
instance.interceptors.response.use(response => {
  removePendingRequest(response.config); // 请求完成后移除
  return response;
}, error => {
  if (axios.isCancel(error)) {
    console.log('请求已取消', error.message);
  } else {
    // 处理其他错误
  }
  return Promise.reject(error);
});

export default instance;

这样,当用户发送重复请求时,之前的请求就会被取消。

加载状态和错误处理

在发送请求时,我们通常会显示一个加载状态,告诉用户正在加载数据。当请求完成后,我们需要隐藏加载状态,并根据响应结果进行相应的处理。

// axios.js
// ...

// 请求拦截器
instance.interceptors.request.use(config => {
  // 显示加载状态
  // ...
  return config;
}, error => {
  return Promise.reject(error);
});

// 响应拦截器
instance.interceptors.response.use(response => {
  // 隐藏加载状态
  // ...

  // 处理响应数据
  if (response.data.code === 200) {
    return response.data;
  } else {
    // 处理错误
    return Promise.reject(response.data);
  }
}, error => {
  // 隐藏加载状态
  // ...

  // 处理错误
  if (axios.isCancel(error)) {
    // ...
  } else {
    // ...
  }
  return Promise.reject(error);
});

export default instance;

在加载状态的显示和隐藏方面,我们可以使用一些 UI 组件库,例如 Element UI 或 Ant Design Vue,来实现更友好的用户体验。

常见问题及解答

1. 如何设置请求超时时间?

可以在 axios.create() 方法中设置 timeout 属性,例如 axios.create({ timeout: 5000 }),表示超时时间为 5 秒。

2. 如何设置请求头?

可以在 axios.create() 方法中设置 headers 属性,例如 axios.create({ headers: { 'Content-Type': 'application/json' } })

3. 如何发送 FormData 格式的数据?

可以使用 FormData 对象来构建表单数据,然后将其作为 config.data 传递给 Axios。

4. 如何处理跨域请求?

需要服务器端配合设置 CORS 策略,或者使用代理服务器来转发请求。

5. 如何在请求中携带 Cookie?

可以在 axios.create() 方法中设置 withCredentials: true

通过以上这些封装,我们可以使 Axios 更加易用和健壮,从而提高我们的开发效率和代码质量。当然,这只是一个基本的封装示例,您可以根据自己的项目需求进行更深入的定制。