javascript fetch(千字长文)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观
在现代 Web 开发中,与服务器进行数据交互是开发者最常见的任务之一。无论是获取用户信息、提交表单,还是加载动态内容,都需要通过 HTTP 请求与后端进行通信。JavaScript Fetch API 作为浏览器内置的现代解决方案,凭借其简洁的语法和强大的功能,已经成为前端开发者处理网络请求的首选工具。
本文将从零开始,通过循序渐进的方式讲解 JavaScript Fetch 的核心概念、使用场景、代码示例及最佳实践。无论你是刚接触网络请求的编程初学者,还是希望深入掌握进阶技巧的中级开发者,都能在本文中找到适合自己的知识。
一、什么是 JavaScript Fetch API?
Fetch API 是一个基于 Promise 的接口,用于发起网络请求并获取资源。它类似于传统的 XMLHttpRequest
(XHR),但语法更简洁,功能更强大。
1.1 为什么选择 Fetch 而不是 XHR?
想象你是一名快递员:
- XHR 像是骑着老式自行车送货,虽然能完成任务,但需要手动调节速度、路线,且中途无法查看包裹状态。
- Fetch 则像驾驶一辆智能电动车,内置导航系统(Promise)和实时追踪功能(异步处理),让整个过程更高效、直观。
Fetch 的核心优势包括:
- 基于 Promise:天然支持异步操作,代码可读性更高。
- 灵活的请求配置:支持自定义请求头、请求方法(GET、POST 等)和请求体。
- 跨平台兼容性:现代浏览器几乎全面支持,且可通过 polyfill 兼容旧版环境。
二、Fetch API 的基础用法
2.1 发起一个 GET 请求
最简单的 GET 请求只需一行代码:
fetch("https://api.example.com/data")
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("请求失败:", error));
代码解析:
fetch(url)
:发起请求,返回一个 Promise 对象。.then(response => ...)
:处理响应对象(response
),需手动调用json()
或text()
将响应体转换为可用格式。- 错误处理:通过
.catch()
捕获请求过程中发生的异常。
2.2 使用 async/await 简化代码
通过 async/await
,可以将异步代码写得更接近同步逻辑:
async function fetchData() {
try {
const response = await fetch("https://api.example.com/data");
const data = await response.json();
console.log(data);
} catch (error) {
console.error("请求失败:", error);
}
}
关键点:
async
关键字:标记函数为异步函数,允许使用await
。await
关键字:暂停函数执行,直到 Promise 完成或拒绝。
三、深入理解 Fetch 的核心概念
3.1 请求方法与 URL 参数
Fetch 支持多种 HTTP 方法,默认为 GET。若需发送 POST 请求,需配置 method
和 body
:
// 发送 POST 请求
fetch("https://api.example.com/submit", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ name: "Alice", age: 25 })
})
.then(response => response.json())
.then(data => console.log("提交成功", data));
参数详解:
method
:指定请求类型(如 POST、PUT、DELETE)。headers
:定义请求头,例如设置Content-Type
为 JSON。body
:请求体内容,需手动序列化为字符串(如 JSON)。
3.2 处理响应对象
Fetch 返回的 response
对象包含以下关键属性和方法:
| 属性/方法 | 说明 |
|-------------------|--------------------------------------------------------------------|
| response.ok
| 布尔值,表示请求是否成功(状态码 200-299 返回 true
)。 |
| response.status
| 返回 HTTP 状态码(如 200、404、500)。 |
| response.json()
| 将响应体解析为 JSON 对象(返回 Promise)。 |
| response.text()
| 将响应体解析为字符串(适用于非 JSON 数据)。 |
实际案例:
fetch("https://api.example.com/data")
.then(response => {
if (!response.ok) {
throw new Error(`HTTP 错误:${response.status}`);
}
return response.json();
})
.then(data => console.log(data));
四、错误处理与网络监控
4.1 全局错误捕获
Fetch 的 .catch()
只能捕获请求过程中发生的网络错误(如 DNS 解析失败、连接超时)。若服务器返回非 2xx 状态码,需通过 response.ok
或 response.status
手动判断:
fetch("https://api.example.com/invalid-endpoint")
.then(response => {
if (!response.ok) {
return response.json().then(error => {
throw new Error(`API 错误:${error.message}`);
});
}
return response.json();
})
.then(data => console.log(data))
.catch(error => console.error(error));
4.2 设置超时机制
某些场景下,请求可能因网络延迟无限期等待。通过 setTimeout
可实现超时控制:
function fetchWithTimeout(url, options, timeout = 5000) {
return Promise.race([
fetch(url, options),
new Promise((_, reject) => setTimeout(() => reject(new Error("请求超时")), timeout))
]);
}
五、进阶技巧与最佳实践
5.1 自定义请求头与身份验证
在需要身份验证的场景中,可通过 headers
添加 Authorization
头:
const token = "your-auth-token";
fetch("https://api.example.com/protected", {
headers: {
Authorization: `Bearer ${token}`
}
});
5.2 处理文件上传
上传文件时,需使用 FormData
对象:
const formData = new FormData();
formData.append("file", fileInput.files[0]);
formData.append("description", "我的图片");
fetch("/upload", {
method: "POST",
body: formData
});
5.3 跨域请求与 CORS
当请求的 URL 域名与当前页面不同,需确保目标服务器配置了正确的 CORS 头:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST
六、与传统 XHR 的对比
尽管 Fetch 是现代标准,但 XHR 仍存在于某些遗留系统中。以下是两者的核心差异:
| 特性 | Fetch API | XMLHttpRequest |
|--------------------|-----------------------------------|-------------------------|
| 异步机制 | Promise | 回调函数或事件监听 |
| 简单性 | 更简洁,无需手动创建对象 | 需调用 new XMLHttpRequest()
|
| 响应处理 | 内置 .json()
等解析方法 | 需手动解析响应体 |
七、常见问题与解决方案
Q1: 为什么我的 POST 请求没有数据?
可能原因:未设置 Content-Type
或未正确序列化请求体。
解决方案:
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ key: "value" })
Q2: 如何在服务端配置 CORS?
在 Express 中,可通过中间件实现:
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
next();
});
结论
JavaScript Fetch API 凭借其简洁的语法、强大的功能和良好的兼容性,已成为现代前端开发中不可或缺的工具。通过本文,我们系统地学习了 Fetch 的基础用法、核心概念、错误处理技巧及进阶应用场景。
无论是发送简单的 GET 请求,还是处理复杂的文件上传和身份验证,Fetch 都能提供直观且高效的解决方案。建议读者通过实际项目练习,逐步掌握其高级功能。未来,随着浏览器技术的演进,Fetch 还将带来更多惊喜,例如对流式传输(Stream)的支持,值得开发者持续关注。
希望本文能帮助你在 Web 开发的道路上更进一步!