axios 教程:从入门到实战 – wiki基地


Axios 教程:从入门到实战

在现代 Web 开发中,与后端进行数据交互是核心功能之一。无论是获取数据、提交表单,还是上传文件,前端都需要通过 HTTP 请求与服务器通信。在 JavaScript 生态系统中,有许多库可以帮助我们完成这项任务,其中最受欢迎、功能最强大的之一就是 Axios

Axios 是一个基于 Promise 的 HTTP 客户端,可以在浏览器和 Node.js 中使用。它拥有简洁的 API、强大的功能和良好的社区支持,成为了许多前端项目的首选网络请求库。

本篇文章将带你从零开始认识 Axios,掌握其基本用法,深入了解其高级特性,并最终学习如何在实际项目中有效地运用它。

1. 初识 Axios:它是什么以及为什么选择它?

1.1 什么是 Axios?

Axios 是一个用于浏览器和 Node.js 的 Promise 风格的 HTTP 客户端。简单来说,它是一个专门用来发送 HTTP 请求的库。

在没有 Axios 之前,前端主要使用原生的 XMLHttpRequest 对象来发送 AJAX 请求。后来,jQuery 的 $.ajax() 方法简化了操作,但它依赖于 jQuery 库本身。随着 Promise 的普及,ES6 推出了原生的 fetch API,它基于 Promise,语法更现代。

然而,Axios 在 XMLHttpRequestfetch 的基础上,提供了更多开箱即用的功能和更好的开发体验。

1.2 为什么选择 Axios?

相较于原生的 XMLHttpRequestfetch API,Axios 具有诸多优势:

  1. 基于 Promise: Axios 的所有请求都返回 Promise,这使得异步操作的处理更加优雅,可以使用 .then().catch() 链式调用,或者结合 async/await 语法,大大简化了代码结构和错误处理。
  2. 浏览器和 Node.js 通用: 同一套代码可以在浏览器端和 Node.js 环境中使用,这对于同构应用(Isomorphic/Universal JavaScript)或构建代理服务非常有用。
  3. 丰富的特性:
    • 支持请求和响应拦截器(Interceptors)。
    • 自动转换 JSON 数据。
    • 提供了防御 XSRF 的机制。
    • 支持取消请求。
    • 提供了一致的 API,无论请求类型(GET, POST 等)。
    • 可以设置请求超时。
    • 支持上传/下载进度的监听。
  4. 更好的错误处理: Axios 在发生错误时会返回一个包含更详细信息的 Error 对象,更容易判断错误类型(如网络错误、超时、服务器返回非 2xx 状态码等)。
  5. 社区活跃: 拥有庞大的用户基础和活跃的社区,遇到问题更容易找到解决方案。

正是因为这些优点,Axios 成为了许多现代前端框架(如 Vue、React)中进行网络请求的首选库。

2. 入门:安装与基本使用

2.1 安装 Axios

使用 npm 或 yarn 进行安装是推荐的方式:

“`bash

使用 npm

npm install axios

使用 yarn

yarn add axios
“`

如果你的项目不使用模块打包工具(如 Webpack, Parcel),或者只是想快速尝试,也可以通过 CDN 引入:

“`html

“`

引入后,全局会有一个 axios 对象。

2.2 基本 GET 请求

最简单的用法是发送一个 GET 请求获取数据:

“`javascript
// 假设我们有一个接口 /api/user?ID=12345
axios.get(‘/api/user?ID=12345’)
.then(function (response) {
// 请求成功时的处理
console.log(response.data); // 响应体数据
console.log(response.status); // HTTP 状态码,如 200
console.log(response.statusText); // 状态文本,如 OK
console.log(response.headers); // 响应头
console.log(response.config); // 请求配置
})
.catch(function (error) {
// 请求失败时的处理
console.error(error);
});

// 也可以使用 async/await 语法,代码更简洁
async function getUser() {
try {
const response = await axios.get(‘/api/user’, {
params: {
ID: 12345
}
});
console.log(response.data);
} catch (error) {
console.error(error);
}
}

getUser();
“`

说明:

  • axios.get(url, [config]) 方法用于发送 GET 请求。url 是请求地址,config 是一个可选的配置对象。
  • GET 请求的参数通常放在 URL 中,或者使用 config 对象中的 params 属性。使用 params 属性时,Axios 会自动将对象转换为查询字符串附加到 URL 后面。
  • then() 方法处理请求成功的情况。它接收一个回调函数,该函数会收到一个 response 对象作为参数。
  • catch() 方法处理请求失败的情况。它接收一个回调函数,该函数会收到一个 error 对象作为参数。
  • response.data 是服务器返回的实际数据,Axios 会自动将其从 JSON 字符串转换为 JavaScript 对象(如果 Content-Type 是 application/json)。
  • 使用 async/await 可以让异步代码看起来像同步代码,提高可读性。记得将调用 axios 的函数标记为 async,并在请求前使用 await。错误处理使用 try...catch 块。

2.3 基本 POST 请求

POST 请求常用于提交数据到服务器:

javascript
// 假设我们要创建一个新用户
axios.post('/api/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response.data);
})
.catch(function (error) {
console.error(error);
});

说明:

  • axios.post(url, data, [config]) 方法用于发送 POST 请求。url 是请求地址,data 是要发送到服务器的数据,config 是可选的配置对象。
  • POST 请求的数据通常放在请求体(Request Body)中。Axios 会自动将 JavaScript 对象序列化为 JSON 字符串,并设置 Content-Typeapplication/json(除非你手动指定其他类型)。

2.4 其他 HTTP 请求方法

Axios 支持所有标准的 HTTP 方法:

  • axios.request(config): 最通用的方法,通过 config 配置 method 类型
  • axios.get(url, [config])
  • axios.delete(url, [config])
  • axios.head(url, [config])
  • axios.options(url, [config])
  • axios.post(url, data, [config])
  • axios.put(url, data, [config])
  • axios.patch(url, data, [config])

这些方法的用法类似,主要区别在于参数的位置(GET/DELETE 等通常将数据放在 URL 或 params 中,POST/PUT/PATCH 通常将数据放在请求体 data 中)。

示例 (DELETE 请求):

javascript
axios.delete('/api/user/12345') // 删除 ID 为 12345 的用户
.then(response => {
console.log('User deleted:', response.data);
})
.catch(error => {
console.error('Delete failed:', error);
});

3. 深入配置:定制你的请求

Axios 允许你在发送请求时进行详细的配置,以满足各种需求。这些配置可以通过传递一个配置对象来实现,通常作为 axios.request(config) 的参数,或者作为 axios.get/post/... 方法的最后一个参数。

以下是一些常用的配置选项:

  • url: 请求的地址。
  • method: 请求方法,如 'get', 'post' 等,默认 'get'
  • baseURL: 将自动加在 url 前面,除非 url 是绝对的。使用 baseURL 便于管理不同环境的接口地址。
  • headers: 自定义请求头。
  • params: 将与请求一起发送的 URL 参数,必须是一个纯对象或 URLSearchParams 对象。
  • data: 作为请求主体被发送的数据,仅适用于 PUT, POST, PATCH 等方法。可以是对象、FormData、Buffer 等类型。对于对象,Axios 会默认序列化为 JSON。
  • timeout: 请求超时时间(毫秒)。如果请求时间超过这个值,请求将被中断。
  • responseType: 响应数据的类型。可以是 'arraybuffer', 'document', 'json', 'text', 'stream'。默认 'json'
  • withCredentials: 表示跨域请求时是否携带 cookie。
  • auth: 提供 HTTP 基础认证凭证,例如 { username: 'admin', password: 'password' }
  • proxy: 配置代理服务器信息。

示例:设置 baseURL, headers 和 timeout

javascript
axios.get('/user/12345', {
baseURL: 'https://api.example.com', // 设置基础URL
headers: {
'X-Requested-With': 'XMLHttpRequest', // 自定义请求头
'Authorization': 'Bearer your_token_here' // 携带认证信息
},
params: {
id: 12345,
status: 'active'
},
timeout: 5000, // 5秒超时
responseType: 'json' // 期望接收JSON数据
})
.then(response => {
console.log(response.data);
})
.catch(error => {
if (error.code === 'ECONNABORTED') {
console.error('Request timed out');
} else {
console.error(error.message);
}
});

3.1 设置全局默认配置

你可以在任何地方设置 Axios 的全局默认配置,这些配置会应用到所有使用该 Axios 实例发送的请求上:

“`javascript
// 设置基础URL
axios.defaults.baseURL = ‘https://api.example.com’;

// 设置通用请求头
axios.defaults.headers.common[‘Authorization’] = ‘AUTH_TOKEN’;
axios.defaults.headers.post[‘Content-Type’] = ‘application/x-www-form-urlencoded’; // POST请求默认Content-Type

// 设置超时时间
axios.defaults.timeout = 10000; // 10秒

// 设置跨域是否携带 cookie
axios.defaults.withCredentials = true;

// 后续的请求将使用这些默认配置,除非在请求时被覆盖
axios.get(‘/user/12345’).then(…);
“`

注意: 全局默认配置会影响 所有 使用 axios 对象发起的请求。如果你需要为不同类型的请求或不同模块设置不同的默认配置,建议使用 axios.create() 创建 Axios 实例(详见后面)。

配置的优先级:请求配置 (config) > 实例配置 (instance.defaults) > 全局默认配置 (axios.defaults)。

4. 拦截器(Interceptors):请求与响应的“守卫”

拦截器是 Axios 最强大的功能之一。它允许你在请求发送前或响应返回后,对请求或响应数据进行统一的处理。这对于添加认证信息、记录日志、处理错误等非常有用。

Axios 支持两种类型的拦截器:请求拦截器和响应拦截器。

4.1 请求拦截器

在请求被发送到服务器之前,可以被请求拦截器拦截。你可以在这里修改请求配置,比如添加认证 Token。

javascript
// 添加一个请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么,例如添加 token
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = 'Bearer ' + token;
}
// 可以在这里添加 loading 动画
console.log('请求拦截器:', config);
return config; // 必须返回 config
}, function (error) {
// 对请求错误做些什么
console.error('请求拦截器错误:', error);
return Promise.reject(error); // 必须返回 Promise.reject(error)
});

说明:

  • axios.interceptors.request.use(fulfilled, rejected) 方法接收两个函数作为参数。
  • 第一个函数 fulfilled 在请求成功发送前被调用,接收当前的请求配置 config 作为参数。你可以在这里修改 config 对象,然后必须返回修改后的 config
  • 第二个函数 rejected 在请求发生错误(比如网络问题)时被调用,接收一个 error 对象作为参数。你必须返回 Promise.reject(error)
  • 请求拦截器常用于:
    • 在请求头中添加认证信息(如 Bearer Token)。
    • 显示全局 Loading 状态。
    • 记录请求日志。
    • 对请求参数进行加密或格式化。

4.2 响应拦截器

在服务器响应返回后,但在 .then().catch() 处理之前,可以被响应拦截器拦截。你可以在这里统一处理响应数据或错误。

``javascript
// 添加一个响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么,例如统一处理返回的数据结构
console.log('响应拦截器 - 成功:', response);
// 可以在这里关闭 loading 动画
// 假设后端返回的数据结构是 { code: 0, message: 'success', data: {...} }
// 这里只返回 data 部分
// if (response.data && response.data.code === 0) {
// return response.data.data;
// } else {
// // 如果业务状态码不为 0,也视为错误处理
// return Promise.reject(response.data);
// }
return response; // 通常返回 response 或 response.data
}, function (error) {
// 对响应错误做点什么
console.error('响应拦截器 - 失败:', error.response);
// 可以在这里关闭 loading 动画,并统一处理错误提示
if (error.response) {
// 服务器返回了非 2xx 的状态码
switch (error.response.status) {
case 401:
console.error('Unauthorized: 请重新登录');
// 例如:跳转到登录页
// router.push('/login');
break;
case 403:
console.error('Forbidden: 没有权限');
break;
case 404:
console.error('Not Found: 请求的资源不存在');
break;
case 500:
console.error('Internal Server Error: 服务器内部错误');
break;
// 更多错误状态码处理
default:
console.error(
HTTP Error ${error.response.status}: ${error.response.statusText}`);
}
} else if (error.request) {
// 请求已经发送,但没有收到响应(比如网络中断、服务器无响应)
console.error(‘No Response: 服务器没有响应’);
} else {
// 在设置请求时发生了一些事情,触发了错误
console.error(‘Request Error:’, error.message);
}

// 如果是请求取消错误
if (axios.isCancel(error)) {
   console.log('请求被取消:', error.message);
}

return Promise.reject(error); // 必须返回 Promise.reject(error)

});
“`

说明:

  • axios.interceptors.response.use(fulfilled, rejected) 方法同样接收两个函数。
  • 第一个函数 fulfilled 在响应成功返回(状态码为 2xx)时调用,接收 response 对象作为参数。你可以在这里统一处理响应数据,然后返回处理后的数据(通常是 response.dataresponse 对象本身)。
  • 第二个函数 rejected 在响应发生错误(状态码非 2xx,或者网络错误等)时调用,接收 error 对象作为参数。你必须返回 Promise.reject(error)
  • 响应拦截器常用于:
    • 统一处理后端返回的业务状态码。
    • 根据不同的 HTTP 状态码进行统一错误提示(如 401 未授权、404 未找到、500 服务器错误)。
    • 处理需要刷新 Token 的情况。
    • 隐藏全局 Loading 状态。
    • 记录响应日志。

4.3 移除拦截器

当你不再需要某个拦截器时,可以将其移除。use 方法会返回一个数字 ID,用于移除拦截器:

javascript
const myInterceptorId = axios.interceptors.request.use(function () {/* ... */});
// 移除拦截器
axios.interceptors.request.eject(myInterceptorId);

5. 错误处理

Axios 在请求失败时会抛出错误,可以通过 .catch()try...catch 捕获。Axios 的 error 对象比原生的更丰富,方便我们定位问题。

一个典型的 Axios 错误对象包含以下属性:

  • error.config: 生成错误的请求配置对象。
  • error.request: 如果请求已发出但没有收到响应,则包含该请求信息 (XMLHttpRequest 实例在浏览器中,http.ClientRequest 实例在 Node.js 中)。
  • error.response: 如果服务器返回了非 2xx 的状态码,则包含该响应信息。它包含 data, status, headers 等属性。
  • error.message: 错误消息字符串,如 “Network Error”, “timeout of 5000ms exceeded”。
  • error.code: 请求中断的原因(仅在某些情况下存在),例如 'ECONNABORTED' 表示超时。
  • axios.isCancel(error): 一个帮助函数,判断错误是否是由于请求取消引起的。

在响应拦截器的错误处理部分,我们已经看到了如何根据 error.response.statuserror.request 来区分不同类型的错误并进行处理。在实际开发中,建立一个健壮的错误处理机制是非常重要的。

6. 并发请求

Axios 提供了 axios.all() 方法来并发执行多个请求,并等待所有请求都完成后统一处理。

“`javascript
function getUserAccount() {
return axios.get(‘/user/12345’);
}

function getUserPermissions() {
return axios.get(‘/permissions/12345’);
}

// 使用 axios.all() 并发请求
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (accountResponse, permissionsResponse) {
// 两个请求都成功完成
console.log(‘Account Data:’, accountResponse.data);
console.log(‘Permissions Data:’, permissionsResponse.data);
}))
.catch(function (error) {
// 任何一个请求失败都会进入这里
console.error(‘One of the requests failed:’, error);
});
“`

说明:

  • axios.all(iterable) 接收一个 Promise 数组(或其他可迭代对象),返回一个新的 Promise。
  • 当数组中的所有 Promise 都成功时,返回的 Promise 会成功,并将一个包含所有 Promise 结果的数组作为值传递给 .then()
  • 当数组中的任何一个 Promise 失败时,返回的 Promise 会立即失败,并将第一个失败的 Promise 的错误作为值传递给 .catch()
  • axios.spread(callback) 是一个帮助函数,用于将 axios.all() 返回结果数组展开作为参数传递给 .then() 的回调函数,使代码更具可读性。

7. 创建 Axios 实例

在大型应用中,你可能需要与多个不同的后端服务交互,或者在同一个应用中对不同类型的请求应用不同的默认配置或拦截器。这时,使用 axios.create() 创建一个或多个 Axios 实例就非常有用。

axios.create([config]) 方法接受一个配置对象,返回一个新的 Axios 实例。这个实例拥有所有 Axios 的方法(get, post, interceptors 等),并且会继承创建时传入的配置作为其默认配置。

“`javascript
// 创建一个用于与用户相关的 API 交互的实例
const userApi = axios.create({
baseURL: ‘https://api.example.com/users’,
timeout: 5000,
headers: {‘X-Custom-Header’: ‘foobar’}
});

// 创建一个用于与商品相关的 API 交互的实例
const productApi = axios.create({
baseURL: ‘https://api.example.com/products’,
timeout: 8000,
headers: {‘Authorization’: ‘Bearer another_token’}
});

// 使用 userApi 实例发送请求
userApi.get(‘/123’) // 请求地址将是 https://api.example.com/users/123
.then(response => console.log(response.data));

// 使用 productApi 实例发送请求
productApi.post(‘/’, { name: ‘New Product’ }) // 请求地址将是 https://api.example.com/products/
.then(response => console.log(response.data));

// 实例也可以添加自己的拦截器,不会影响全局的 axios 或其他实例
userApi.interceptors.request.use(config => {
console.log(‘User API 请求拦截器:’, config);
return config;
});
“`

好处:

  • 模块化配置: 将不同模块的接口配置(如 baseURL, timeout, headers)隔离开来。
  • 独立的拦截器: 每个实例可以拥有自己的请求和响应拦截器,互不干扰。这对于处理不同的认证机制或错误处理逻辑非常方便。
  • 代码组织: 使代码结构更清晰,易于维护。

在实际项目中,通常会为不同的后端服务或不同的业务模块创建单独的 Axios 实例。

8. 实战应用:在项目中更好地使用 Axios

仅仅知道 Axios 的基本用法和特性是不够的,如何在实际项目中有效地组织和使用它,是“从入门到实战”的关键。

8.1 统一管理 API 请求

避免在组件或业务逻辑中直接调用 axios.get('/api/xxx')。更好的做法是将所有的 API 请求封装成函数,统一管理。

创建一个 api.jsservices/api.js 文件:

“`javascript
// services/api.js

import axios from ‘axios’;

// 创建一个 Axios 实例,可以根据需要配置 baseURL、超时等
const service = axios.create({
baseURL: process.env.VUE_APP_API_BASE_URL || ‘/api’, // 从环境变量获取基础URL
timeout: 10000 // 请求超时时间
});

// 添加请求拦截器
service.interceptors.request.use(
config => {
// 在发送请求之前做些什么
const token = localStorage.getItem(‘accessToken’); // 假设 token 存储在 localStorage
if (token) {
// 让每个请求携带自定义 token 请根据实际情况自行修改
config.headers[‘Authorization’] = ‘Bearer ‘ + token;
}
// 可以添加 loading 动画
// store.commit(‘showLoading’);
return config;
},
error => {
// 对请求错误做些什么
console.error(‘Request Error:’, error); // for debug
// store.commit(‘hideLoading’);
return Promise.reject(error);
}
);

// 添加响应拦截器
service.interceptors.response.use(
response => {
// 对响应数据做些什么
// store.commit(‘hideLoading’);

// 统一处理后端返回的业务状态码
const res = response.data;

// 假设后端约定 code 为非 0 时表示错误
if (res.code !== 0) {
  // 弹出错误提示
  // Message({
  //   message: res.message || 'Error',
  //   type: 'error',
  //   duration: 5 * 1000
  // });

  // 401: Token 失效/未登录
  if (res.code === 401) {
    // 清除 token,跳转到登录页
    // store.dispatch('user/resetToken').then(() => {
    //   location.reload();
    // });
    console.error('Token 失效,请重新登录');
  }

  // 如果需要中断 Promise 链,可以返回 Promise.reject()
  return Promise.reject(new Error(res.message || 'Error'));
} else {
  // 返回实际的数据
  return res.data; // 通常后端把数据放在 data 字段里
}

},
error => {
// 对响应错误做些什么 (非 2xx 状态码或网络错误)
// store.commit(‘hideLoading’);
console.error(‘Response Error:’, error); // for debug

let message = error.message;
if (error.response) {
    // 服务器返回了非 2xx 的状态码
    message = `请求失败: ${error.response.status} ${error.response.statusText}`;
    // 根据 status 处理特定错误
    if (error.response.status === 401) {
         message = '未登录或登录过期,请重新登录';
         // 执行登录页跳转等逻辑
    }
    // ... 其他状态码处理
} else if (error.request) {
     // 请求发出但未收到响应
     message = '网络连接失败,请稍后再试';
}
// 如果是请求取消
if (axios.isCancel(error)) {
   message = '请求已取消';
}


// 弹出错误提示
// Message({
//   message: message,
//   type: 'error',
//   duration: 5 * 1000
// });

return Promise.reject(error);

}
);

// 将实例导出,供其他模块使用
export default service;
“`

然后,在其他文件中创建具体的 API 函数:

“`javascript
// api/user.js

import request from ‘@/services/api’; // 引入上面创建的 Axios 实例

export function login(data) {
return request({
url: ‘/auth/login’, // 会拼接 baseURL
method: ‘post’,
data // 请求体数据
});
}

export function getUserInfo(userId) {
return request({
url: /user/${userId},
method: ‘get’
});
}

export function updateUser(userId, data) {
return request({
url: /user/${userId},
method: ‘put’,
data
});
}

// 在组件中使用
// import { login, getUserInfo } from ‘@/api/user’;
// login({ username: ‘…’, password: ‘…’ }).then(response => { … }).catch(error => { … });
“`

这样做的好处:

  • 代码复用: 统一的请求配置、错误处理、认证逻辑都在 services/api.js 中处理。
  • 易于维护: 所有的 API 请求都在 api 文件夹下,查找和修改方便。
  • 职责分离: 业务组件只调用 API 函数,不关心底层请求细节。
  • 环境切换: 只需要修改 baseURL 就可以切换开发、测试、生产环境的接口地址。

8.2 处理认证(Tokens)

使用拦截器是处理认证 Token 的常用方式:

  • 请求拦截器: 在每个请求发送前,从本地存储(localStorage, sessionStorage, Vuex/Redux State)中获取 Token,并添加到请求头中(通常是 Authorization: Bearer <Token>)。
  • 响应拦截器: 如果响应状态码是 401 (Unauthorized),说明 Token 失效或未登录。可以在这里清除本地存储的 Token,并跳转到登录页面。如果后端有返回新的 Token 或刷新 Token 的机制,也可以在成功响应中更新本地存储的 Token。

8.3 请求取消(Cancellation)

有时候用户在请求完成前切换了页面,或者发起了新的同类请求,此时之前的请求就可能需要取消,以节省资源并避免潜在的竞态条件问题。

Axios 支持两种取消方式:CancelToken (旧) 和 AbortController (新)。推荐使用 AbortController,因为它是一个 Web 标准 API。

使用 AbortController

“`javascript
// 在需要取消请求的地方
const controller = new AbortController();
const signal = controller.signal;

axios.get(‘/api/data’, { signal: signal })
.then(response => {
console.log(‘请求成功:’, response.data);
})
.catch(error => {
if (axios.isCancel(error)) {
console.log(‘请求被取消:’, error.message);
} else {
console.error(‘请求错误:’, error);
}
});

// 在需要取消请求的时机调用
// 例如:组件卸载时,或者用户进行新的搜索时
// controller.abort(); // 取消请求
“`

在实际应用中,通常将 AbortController 实例与组件或特定的操作关联起来,以便在适当的时候调用 abort()。例如,在 Vue/React 组件的 beforeDestroy/componentWillUnmount 生命周期钩子中取消未完成的请求。

8.4 显示 Loading 状态

请求过程中通常需要显示加载动画,提示用户正在等待。这也可以通过拦截器实现:

  • 请求拦截器: 在请求发送前,显示 Loading 状态。
  • 响应拦截器(成功和失败): 在请求成功或失败返回后,隐藏 Loading 状态。

如果你有多个并发请求,可能需要一个计数器来管理 Loading 状态,只有当所有请求都完成后才隐藏 Loading。

“`javascript
let requestCount = 0;

// 请求拦截器
service.interceptors.request.use(config => {
requestCount++;
// 显示 Loading
// if (requestCount === 1) { showLoading(); }
return config;
});

// 响应拦截器 (成功)
service.interceptors.response.use(response => {
requestCount–;
// 隐藏 Loading
// if (requestCount === 0) { hideLoading(); }
return response;
}, error => {
// 响应拦截器 (失败)
requestCount–;
// 隐藏 Loading
// if (requestCount === 0) { hideLoading(); }
return Promise.reject(error);
});

// hideLoading 函数需要处理 Promise.reject 后的异步性,确保在 Promise 链结束时隐藏
// 实际实现可能需要更复杂的逻辑,比如使用 finally 钩子或者在组件层面管理 loading 状态
“`

更健壮的 Loading 管理通常是在组件或页面级别,结合请求状态(如 isLoading 布尔值)来控制。

8.5 上传文件

Axios 可以很方便地上传文件,通常通过 FormData 对象来实现:

“`javascript
const formData = new FormData();
const fileInput = document.getElementById(‘file’); // 获取文件输入的DOM元素

if (fileInput.files && fileInput.files[0]) {
formData.append(‘file’, fileInput.files[0]); // ‘file’ 是后端接收文件的字段名
formData.append(‘userId’, 123); // 也可以添加其他普通字段

axios.post(‘/api/upload’, formData, {
headers: {
‘Content-Type’: ‘multipart/form-data’ // 重要的头部设置
},
onUploadProgress: function(progressEvent) {
// 监听上传进度
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
console.log(‘Upload Progress:’, percentCompleted + ‘%’);
}
})
.then(response => {
console.log(‘Upload successful:’, response.data);
})
.catch(error => {
console.error(‘Upload failed:’, error);
});
} else {
console.warn(‘请选择要上传的文件。’);
}
“`

注意:

  • FormData 对象用于构建键值对集合,可以包含文件和其他普通字段。
  • 发送 FormData 时,需要设置 Content-Type'multipart/form-data'。Axios 在发送 FormData 对象时会自动设置,但明确写出来更清晰。
  • onUploadProgress 回调函数可以用于监听文件上传进度,方便实现进度条功能。

9. 与 Fetch API 的简单比较

特性/库 Axios Fetch API
Promise 基于 Promise 基于 Promise
浏览器支持 兼容性更好 (基于 XMLHttpRequest) 部分旧浏览器不支持
Node.js 支持 不支持 (需要 polyfill 或第三方库,如 node-fetch)
拦截器 内置支持 不支持,需要手动实现或第三方库
自动 JSON 响应数据自动转换为 JSON 需要手动调用 .json() 方法转换响应体
错误处理 HTTP 状态码非 2xx 时自动进入 .catch() HTTP 状态码非 2xx (如 404, 500) 也会进入 .then(),需要手动检查 response.okresponse.status
请求取消 内置支持 (CancelToken / AbortController) 基于 Web 标准 AbortController (较新)
发送数据 对于 POST 等方法,直接传递对象即可 需要手动通过 JSON.stringify() 序列化,并设置 Content-Type
XSRF 防御 内置支持

总的来说,Axios 在功能丰富度和开发便捷性方面通常优于原生的 Fetch API,尤其是在需要拦截器、自动 JSON 转换和更好的错误处理的大型项目中。Fetch API 作为原生标准,在简单场景下或需要更底层控制时也是一个不错的选择。

10. 总结

Axios 作为一款强大的 HTTP 客户端,凭借其 Promise 化的调用方式、丰富的配置项、灵活的拦截器机制以及浏览器/Node.js 通用性,成为了现代前端开发中进行网络请求的首选。

从基本的 GET/POST 请求,到深入的配置、拦截器、错误处理、并发请求,再到创建实例和实战中的 API 统一管理、认证、取消、文件上传等高级应用,Axios 提供了全面的解决方案。

掌握 Axios 的使用,不仅能让你更高效地与后端交互,也能帮助你构建更健壮、可维护的应用。最好的学习方法是边学边练,尝试在你的项目中使用 Axios,并根据实际需求探索其更多功能。

希望这篇详细的教程能帮助你从 Axios 的入门者成长为能够将其运用到实战中的熟练开发者!

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部