js fetch(超详细)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新开坑项目:《Spring AI 项目实战》 正在持续爆肝中,基于 Spring AI + Spring Boot 3.x + JDK 21..., 点击查看 ;
- 《从零手撸:仿小红书(微服务架构)》 已完结,基于
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+ 小伙伴加入学习 ,欢迎点击围观
了解 JavaScript 的现代化网络请求工具:js fetch
在现代 Web 开发中,与服务器进行数据交互是核心需求之一。无论是获取天气信息、加载用户列表,还是提交表单数据,都需要可靠的网络请求工具。js fetch 是 JavaScript 原生提供的现代化 API,它以简洁的语法和灵活的配置选项,成为开发者首选的 HTTP 客户端工具。本文将从基础用法到高级技巧,逐步解析这一工具的原理与实践。
一、为什么选择 js fetch?
在 js fetch 出现之前,开发者主要依赖 XMLHttpRequest
(简称 XHR)或第三方库(如 jQuery 的 $.ajax
)来发送网络请求。然而,这些方案存在明显不足:
- XHR 的语法繁琐:需要手动配置多个属性,代码可读性差;
- 回调地狱问题:嵌套的回调函数导致代码难以维护;
- 缺乏统一标准:第三方库的 API 设计差异较大,学习成本高。
js fetch 的诞生彻底改变了这一局面。它基于现代 JavaScript 的 Promise
语法,支持 async/await
语法糖,解决了回调嵌套问题;同时提供统一的 API 设计,简化了 HTTP 请求的配置与响应处理。
二、快速上手:基础用法与核心概念
1. 最简单的 GET 请求
发送 GET 请求是最常见的操作,例如获取公开数据接口的响应:
fetch("https://api.example.com/data")
.then(response => {
// 处理响应数据
console.log("Status:", response.status);
return response.json(); // 解析 JSON 格式数据
})
.then(data => {
console.log("Data:", data);
})
.catch(error => {
console.error("Error:", error);
});
关键点解析:
fetch()
返回一个Promise
,成功时返回Response
对象,失败时触发catch
;response.json()
将响应体解析为 JSON 对象,同样返回Promise
;- 链式调用(
.then().then().catch()
)是处理异步操作的标准方式。
2. 配置选项与 POST 请求
除了 GET 请求,我们常常需要发送 POST 请求以提交数据。例如,向服务器提交表单:
const formData = {
username: "user123",
email: "user@example.com"
};
fetch("https://api.example.com/submit", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(formData)
})
.then(response => response.json())
.then(data => console.log("Success:", data))
.catch(error => console.error("Error:", error));
配置对象详解:
| 属性名 | 作用说明 |
|--------------|--------------------------------------------------------------------------|
| method
| 指定 HTTP 方法(如 GET、POST、PUT 等,默认为 GET) |
| headers
| 设置请求头,例如指定 Content-Type
或认证信息 |
| body
| 发送请求体,需与 Content-Type
匹配(如 JSON 需要 JSON.stringify()
) |
| mode
| 控制跨域行为,常用值为 cors
(默认)或 no-cors
|
三、深入理解:响应处理与错误捕获
1. 响应对象的详细解析
fetch
返回的 Response
对象包含丰富的信息:
- 状态码:
response.status
返回 HTTP 状态码(如 200 表示成功,404 表示未找到); - 响应体:通过
response.text()
、response.json()
或response.blob()
解析不同格式的数据; - 响应头:
response.headers.get("Header-Name")
可获取服务器返回的自定义头信息。
2. 错误处理的两种模式
模式一:链式 catch
fetch("https://api.example.com/invalid")
.then(response => {
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
return response.json();
})
.catch(error => console.error("Error:", error));
模式二:async/await
语法
async function fetchData() {
try {
const response = await fetch("https://api.example.com/data");
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
const data = await response.json();
console.log("Data:", data);
} catch (error) {
console.error("Error:", error);
}
}
对比说明:
- 链式
then/catch
需要手动抛出错误(如response.ok
检查); async/await
语法更接近同步代码结构,但需在async
函数内使用。
四、进阶技巧:优化与高级场景
1. 使用 FormData
上传文件
当需要上传文件时,FormData
是更自然的选择:
const form = new FormData();
form.append("username", "user123");
form.append("avatar", fileInput.files[0]); // fileInput 是 <input type="file">
fetch("https://api.example.com/upload", {
method: "POST",
body: form
})
.then(response => response.text())
.then(data => console.log("Upload result:", data));
优势:
- 自动设置正确的
Content-Type
(如multipart/form-data
); - 支持大文件传输,无需手动编码。
2. 流式处理大文件
对于大文件下载或实时数据流,可使用 ReadableStream
:
fetch("https://api.example.com/large-file")
.then(response => response.body.pipeThrough(new TextDecoderStream()))
.then(stream => {
const reader = stream.getReader();
return readStream(reader); // 自定义读取逻辑
});
适用场景:实时日志监控、视频流传输等需要逐步处理数据的场景。
3. 跨域问题与 mode
配置
当请求第三方接口时,需确保服务器允许跨域请求(CORS)。若遇到问题,可尝试以下配置:
fetch("https://api.example.com/data", {
mode: "cors" // 明确启用跨域请求(默认值)
});
注意:服务器需设置 Access-Control-Allow-Origin
响应头,否则请求将失败。
五、性能优化与最佳实践
1. 缓存控制与超时处理
通过 Cache-Control
头或 setTimeout
实现请求超时:
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 3000); // 3秒超时
fetch("https://api.example.com/data", {
signal: controller.signal
})
.then(response => {
clearTimeout(timeoutId);
return response.json();
})
.catch(error => {
if (error.name === "AbortError") {
console.log("Request timed out!");
}
});
2. 合并多个请求与节流
使用 Promise.all()
同时发送多个请求:
Promise.all([
fetch("https://api.example.com/data1"),
fetch("https://api.example.com/data2")
])
.then(responses => {
return Promise.all(responses.map(r => r.json()));
})
.then(data => {
console.log("All data:", data);
});
六、对比与替代方案
尽管 js fetch 功能强大,但某些场景可能需要其他工具:
XMLHttpRequest
:兼容性更好(支持旧版浏览器),但代码冗长;- Axios:基于
fetch
的封装,提供更友好的 API(如axios.get()
)和拦截器功能; navigator.sendBeacon()
:用于发送非关键数据(如日志),确保页面卸载时也能发送。
结论
从基础的 GET/POST 请求到高级的流式处理,js fetch 凭借其简洁的语法和强大的功能,已成为现代 Web 开发的基石。通过合理配置请求头、处理响应流、优化性能,开发者可以高效地构建与服务器交互的复杂应用。无论是初学者还是中级开发者,掌握这一工具都能显著提升开发效率,为构建响应式、流畅的 Web 应用打下坚实基础。
实践建议:尝试用 fetch
实现一个天气查询工具或简单的 REST API 客户端,逐步掌握从配置到错误处理的完整流程。