讲解
fetch 是浏览器内置的现代网络请求 API,基于 Promise,取代了老旧的 XMLHttpRequest。最基本的用法是 const response = await fetch(url):它只完成「发出请求并拿到响应头」这一步,读取响应体要再调 response.json()(解析 JSON)或 response.text()(读文本),这些方法同样返回 Promise。response.ok(状态码 200-299)和 response.status 用来判断请求是否成功。
fetch 有个著名的反直觉设计:只有网络层失败(断网、DNS 失败、跨域被拦)才会 reject;HTTP 错误状态(404、500)照样 resolve——你必须自己检查 response.ok,否则 404 的响应体可能被当成功数据解析。POST 等带数据的请求要配置第二个参数:method、headers('Content-Type': 'application/json')、body(JSON.stringify 后的字符串)。
生产级的 fetch 还要处理两件事:超时与取消——用 AbortController,把 controller.signal 传给 fetch,需要取消时调 controller.abort(),fetch 会以 AbortError 拒绝;配合 setTimeout 就是超时控制。错误处理的完整姿势:try/catch 接住网络错误与中止,if (!response.ok) 处理 HTTP 错误,json 解析失败再兜底一层。
示例
fetch 依赖网络环境,无法在本页沙盒运行,以下代码请在浏览器控制台体验(jsonplaceholder 是公开的测试接口):
// GET:获取并解析 JSON
async function loadPost() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
if (!response.ok) {
throw new Error('HTTP 错误:' + response.status); // fetch 不会因 404/500 自动 reject
}
const post = await response.json();
console.log('标题:', post.title);
return post;
} catch (err) {
console.error('请求失败:', err.message);
}
}
// POST:提交 JSON 数据
async function createPost() {
const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: '你好', body: '正文内容', userId: 1 }),
});
if (!response.ok) throw new Error('提交失败:' + response.status);
return response.json();
}
// 超时与取消:AbortController
async function fetchWithTimeout(url, timeoutMs = 5000) {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(url, { signal: controller.signal });
if (!response.ok) throw new Error('HTTP ' + response.status);
return await response.json();
} catch (err) {
if (err.name === 'AbortError') throw new Error('请求超时');
throw err;
} finally {
clearTimeout(timer);
}
}
常见坑
- 以为 404 会进 catch:fetch 只在网络故障时 reject,HTTP 错误要检查 response.ok 或 response.status,这是新手第一大坑。
- 忘记 await response.json():直接 console.log(response) 打印的是响应对象不是数据;response.json() 也是异步的。
- 响应体读两次:response.json() 之后不能再 response.text(),body 只能消费一次,报 "body used already"。
- 跨域报错无从下手:fetch 默认受同源策略约束,跨域需要服务端配 CORS 响应头,前端改 mode 绕不过去——这是服务端配置问题。
小结
fetch 发请求、response.json() 取数据;HTTP 错误不 reject,自查 response.ok;AbortController 管超时取消。下一章开始操作网页本身:DOM 基础。