引言
在构建数据驱动的 Vue 应用时,与服务器的通信是核心功能之一。本文将深入介绍如何在 Vue 中使用 axios 与服务器 API 交互,并展示如何封装 API 调用、错误处理和加载状态管理,以及如何将 API 接口统一管理以提高代码的可维护性和复用性。
本章知识点:
- 使用 axios 与服务器 API 交互
- 处理 HTTP 请求和响应
- 管理 API 错误和加载状态
- 封装 HTTP 服务和使用服务工作器
回顾
在之前的章节中,我们学习了 Vue 的基础知识、组件化开发、状态管理、动画与过渡等。现在,我们将转向 Vue 与服务器通信的高级话题。
使用 axios 与服务器 API 交互
Axios 是一个基于
promise 网络请求库,作用于node.js和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和 node.js 中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests , 广泛用于 Vue 应用中,以实现与服务器的异步通信。
Axios 特性:
-
从浏览器创建
XMLHttpRequests -
从 node.js 创建 http 请求
-
支持
Promise API -
拦截请求和响应 -
转换请求和响应数据
-
取消请求 -
超时处理 -
查询参数序列化支持嵌套项处理
-
自动将请求体
序列化
为:
-
- JSON (application/json)
- Multipart / FormData (multipart/form-data)
- URL encoded form (application/x-www-form-urlencoded)
-
将 HTML Form 转换成 JSON 进行请求
-
自动转换 JSON 数据
-
获取浏览器和 node.js 的请求进度,并提供额外的信息(速度、剩余时间) -
为 node.js 设置带宽限制
-
兼容符合规范的
FormData 和 Blob(包括 node.js) -
客户端支持防御
XSRF
安装 axios
首先,确保安装了 axios 库:
bash
bash
复制代码npm install axios
发起 HTTP 请求
使用 axios 发起 GET 和 POST 请求:
js
javascript复制代码// GET请求
axios
.get("https://api.baidu.com/data")
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error("出错:", error);
});
// POST请求
axios
.post("https://api.baidu.com/data", { key: "value" })
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error("出错:", error);
});
请求和响应拦截器
通过拦截器,我们可以统一处理请求前的配置和响应后的数据。
实例演示
js
javascript复制代码import axios from "axios";
const instance = axios.create({
baseURL: "https://api.baidu.com",
timeout: 1000, //设置接口请求超时时间
});
instance.interceptors.request.use(
(config) => {
// 在发送请求之前做些什么
return config;
},
(error) => {
// 对请求错误做些什么
return Promise.reject(error);
}
);
instance.interceptors.response.use(
(response) => {
// 对响应数据做点什么
return response;
},
(error) => {
// 对响应错误做点什么
return Promise.reject(error);
}
);
管理 API 错误和加载状态
有效的错误处理和加载状态管理能够提升用户体验。
错误处理
集中管理 API 错误,例如创建一个错误处理服务。
加载状态
使用 Vue 的响应式系统来管理加载状态。
实例演示
js
javascript复制代码// 在Vue组件中管理加载状态和错误
data() {
return {
isLoading: false,
error: null
};
},
methods: {
async fetchData() {
this.isLoading = true;
try {
const response = await http.get('/data');
// 处理数据
} catch (error) {
this.error = error;
console.error('请求出错:', error);
} finally {
this.isLoading = false;
}
}
}
封装 HTTP 服务
封装 HTTP 服务是提高代码复用性和简化 API 调用的关键步骤。
创建 HTTP 服务模块
js
javascript复制代码// httpService.js
import axios from "axios";
// 创建axios实例
const instance = axios.create({
baseURL: "https://api.baidu.com",
timeout: 1000, //设置接口请求超时时间
headers: { "X-Custom-Header": "foobar" },
});
// 请求拦截器
instance.interceptors.request.use(
(config) => {
config.headers["Authorization"] = `Bearer ${localStorage.getItem("token")}`;
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 响应拦截器
instance.interceptors.response.use(
(response) => {
return response;
},
(error) => {
if (error.response && error.response.status === 401) {
// 处理未授权错误
console.log("未认证。。:", error.response.data);
}
return Promise.reject(error);
}
);
export default instance;
API 接口封装层
将后端 API 接口统一管理,可以方便其他文件复用。
创建 API 接口文件
js
javascript复制代码// api.js
// 获取用户
export const fetchData = () => httpService.get("/users");
// 创建用户
export const createUser = (userData) => httpService.post("/users", userData);
// 更新用户
export const updateUser = (userId, userData) =>
httpService.put(`/users/${userId}`, userData);
// 删除用户
export const deleteUser = (userId) => httpService.delete(`/users/${userId}`);
在 Vue 组件中使用封装的 API
js
javascript复制代码// UserList.vue
import { fetchData } from "./api";
export default {
data() {
return {
users: [],
isLoading: false,
error: null,
};
},
methods: {
async loadUsers() {
this.isLoading = true;
try {
const response = await fetchData();
this.users = response.data;
} catch (error) {
this.error = error;
console.error("请求用户出错:", error);
} finally {
this.isLoading = false;
}
},
},
mounted() {
this.loadUsers();
},
};
请求取消
Axios 提供了两种主要的方法来取消请求,分别是使用 CancelToken 和 AbortController。
以下是这两种方法的基本用法:
- 使用 AbortController
- Axios 支持使用
AbortController来取消请求,这是一种与 fetch API 类似的取消方式。 - 创建一个
AbortController实例,并将其signal属性传递给 Axios 请求的signal配置项。 - 调用
abort方法来取消请求。
javascript复制代码const controller = new AbortController(); // 创建 AbortController 实例
axios
.get("/foo/bar", {
signal: controller.signal, // 将 signal 传递给请求
})
.then(function (response) {
// 请求成功处理
})
.catch(function (error) {
// 请求失败处理
});
// 取消请求
controller.abort();
- 使用 CancelToken
(官方已经弃用了)
- 首先,你需要创建一个取消标记(cancel token)。
- 然后,将这个标记与特定的请求关联。
- 当需要取消请求时,调用标记中的
cancel方法。
javascript复制代码import axios from "axios";
const source = axios.CancelToken.source(); // 创建取消标记
axios
.get("/api/data", {
cancelToken: source.token, // 将取消标记与请求关联
})
.then((response) => {
// 请求成功处理
})
.catch((error) => {
if (axios.isCancel(error)) {
console.log("请求被取消", error.message);
} else {
console.log("请求出错", error.message);
}
});
// 取消请求
source.cancel("请求取消的原因");
Axios 与 Fetch 特性对比
| 特性/功能 | Axios | Fetch |
|---|---|---|
| 定义 | Axios 是一个基于 promise 的 HTTP 客户端 | Fetch 是浏览器提供的 API,用于发起网络请求 |
| 浏览器兼容性 | 需要安装 Axios 库 | 无需额外安装,现代浏览器内置支持 |
| Promise | 基于 Promise,易于使用 async/await | 返回 Promise 对象,也支持 async/await |
| 拦截器 | 支持请求和响应拦截器 | 不内置拦截器,需要手动实现 |
| 取消请求 | 支持请求取消,使用 CancelToken 或 AbortController | 支持请求取消,使用 AbortController |
| 请求配置 | 支持全局和局部配置 | 配置较为简单,主要通过 options 对象 |
| 错误处理 | 错误处理较为简单,统一捕获 | 需要手动检查响应状态和处理异常 |
| 超时控制 | 支持请求超时设置 | 不内置超时控制,需要手动实现 |
| JSON 处理 | 自动处理 JSON 数据的请求和响应 | 需要手动处理 JSON 数据的转换 |
| 类型支持 | TypeScript 友好 | TypeScript 支持,但需要额外配置 |
| 测试 | 易于测试和模拟 | 测试和模拟较为复杂,需要额外工具 |
| 社区和文档 | 活跃的社区,丰富的文档和插件 | 标准 API,文档较为官方和简洁 |
| 使用场景 | 适用于复杂的 HTTP 请求处理 | 适用于简单的 HTTP 请求或需要浏览器兼容性的场景 |
共同点:
- 两者都基于 Promise,支持 async/await。
- 两者都支持请求取消。
- 两者都可以处理 JSON 数据。
差异:
- Axios 是一个第三方库,需要安装,而 Fetch 是浏览器内置的 API。
- Axios 提供了更丰富的功能,如拦截器、请求配置、错误处理等。
- Axios 对 TypeScript 更友好,而 Fetch 需要额外配置 TypeScript。
- Axios 的错误处理和超时控制更为简单和直观。
- Fetch 的配置和使用相对简单,但需要手动处理一些功能,如拦截器和超时控制。
fetch 使用示例
基本语法
js
javascript复制代码fetch(url, options)
.then((response) => {
// 处理响应
if (!response.ok) {
throw new Error("网络响应出错");
}
return response.json(); // 假设响应是 JSON 格式
})
.then((data) => console.log(data))
.catch((error) => console.error("请求出错:", error));
参数说明
-
url: 请求的 URL。 -
:
可选参数,可以包含以下属性: -
method: 请求方法,例如GET、POST、PUT、DELETE等。headers: 请求头对象。body: 请求体,对于GET和HEAD请求,这个属性会被忽略。mode: 请求模式,例如cors、no-cors、same-origin。credentials: 凭证类型,例如include、same-origin、omit。cache: 缓存模式,例如default、no-cache、reload、force-cache。redirect: 重定向模式,例如follow、error、manual。referrer: 引用页 URL。integrity: 子资源完整性校验值。
fetch 的高级配置
- 请求发送 :通过
fetchAPI 来发起网络请求 - 请求超时 :通过设置一个超时计时器,并在超时时使用
AbortController取消请求。 - 取消请求 :通过
AbortController实现请求的取消。 - JSON 处理 :手动调用
.json()方法来解析响应体中的 JSON 数据。 - 错误处理 :通过
.catch()捕获请求过程中的错误,并手动处理不同类型的错误。 - 请求配置 :通过
requestOptions对象来配置请求方法、头部等信息。
js
javascript复制代码// 1. 定义 fetch 请求函数
function fetchData(url, options = {}) {
const controller = new AbortController(); // 支持取消请求
const signal = controller.signal;
// 设置请求超时,需要手动实现
const timeoutId = setTimeout(() => controller.abort(), 5000); // 5秒超时
// 配置请求选项
const fetchOptions = {
...options, // 允许传入自定义配置
signal, // 将 AbortController 的 signal 绑定到请求
};
// 发起 fetch 请求
return fetch(url, fetchOptions)
.then((response) => {
if (!response.ok) {
// 需要手动检查响应状态
throw new Error("网络响应出错");
}
return response.json(); // 手动处理 JSON 数据转换
})
.catch((error) => {
if (error.name === "AbortError") {
console.error("请求中止:", error.message);
} else {
console.error("请求出错:", error);
}
throw error; // 需要手动处理异常
});
}
// 2. 使用 fetch 请求函数
const url = "https://api.baidu.com/data";
// 配置请求选项,例如设置请求头
const requestOptions = {
method: "GET",
headers: {
"Content-Type": "application/json",
},
};
fetchData(url, requestOptions)
.then((data) => console.log("接收的数据:", data))
.catch((error) => console.error("请求出错:", error));
// 3. 取消请求
// 在某个条件下取消请求,例如用户点击取消按钮
setTimeout(() => {
console.log("取消请求...");
// 调用 AbortController 的 abort 方法取消请求
clearTimeout(timeoutId); // 清除超时
controller.abort("用户取消 "); // 取消请求
}, 3000); // 假设在3秒后取消请求
结语
通过本站的学习,我们掌握了如何在 Vue 中使用 axios 与服务器 API 进行交互,封装 HTTP 服务,处理 HTTP 请求和响应,以及管理 API 错误和加载状态,fetch 的探索。此外,我们还学习了如何将 API 接口统一管理,以提高代码的可维护性和复用性。
互动交流
欢迎在文章下方留言,分享学习 Vue 与服务器通信的心得体会,或提出在使用过程中遇到的问题。我们将在后续的文章中提供解答和指导。