引言
在构建数据驱动的 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
复制代码npm install axios
发起 HTTP 请求
使用 axios 发起 GET 和 POST
请求:
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);
});
请求和响应拦截器
通过拦截器
,我们可以统一处理
请求前的配置和响应后的数据。
实例演示
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 的响应式系统来管理加载状态。
实例演示
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 服务模块
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 接口文件
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
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
使用示例
基本语法
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。 -
-
options
- 可选参数,可以包含以下属性:
-
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 的高级配置
- 请求发送:通过
fetch
API 来发起网络请求 - 请求超时:通过设置一个超时计时器,并在超时时使用
AbortController
取消请求。 - 取消请求:通过
AbortController
实现请求的取消。 - JSON 处理:手动调用
.json()
方法来解析响应体中的 JSON 数据。 - 错误处理:通过
.catch()
捕获请求过程中的错误,并手动处理不同类型的错误。 - 请求配置:通过
requestOptions
对象来配置请求方法、头部等信息。
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 与服务器通信的心得体会,或提出在使用过程中遇到的问题。我们将在后续的文章中提供解答和指导。