fetch API是现代浏览器内置的网络请求接口,基于Promise设计,用于替代传统的XMLHttpRequest实现异步数据获取。它支持多种HTTP请求方法和自定义请求配置,使用起来更加符合现代JavaScript的异步编程习惯。fetch返回的Promise对象可以被链式调用,也可以被async/await语法展开,这使得异步流程的控制更加灵活,也逐渐成为前端与后端通信的主流方案。本文将从fetch的基本用法开始,逐步介绍GET请求、POST请求、异步优化以及常见注意事项。

fetch API基本用法
fetch API的核心是一个全局函数fetch,它接收一个请求地址作为参数,并返回一个Promise对象。这个Promise在请求完成后会解析为一个Response对象,Response对象中封装了响应状态、响应头、响应体等关键信息。与过去的XMLHttpRequest不同,fetch不需要手动监听readystatechange事件,也不需要专门处理onload、onerror等回调,所有逻辑都统一在Promise的then和catch中完成。
为了正确处理不同HTTP状态码,开发者需要主动检查response.ok属性。response.ok是一个布尔值,当HTTP状态码在200到299之间时为true,否则为false。如果状态码是404或500,fetch的Promise仍然会resolve,只是response.ok变为false,因此必须在第一个then中判断该值并抛出Error,才能让后续的catch捕获并处理。
发起GET请求获取JSON数据
最常见的场景是发起GET请求获取后端返回的JSON格式数据。基本写法如下:
// 发起GET请求获取用户列表
fetch('https://ipipp.com/api/users')
.then(response => {
// 判断响应状态是否成功
if (!response.ok) {
throw new Error('请求失败,状态码:' + response.status);
}
// 将响应解析为JSON格式
return response.json();
})
.then(data => {
// 处理获取到的数据
console.log('获取到的用户数据:', data);
})
.catch(error => {
// 捕获请求或解析过程中的错误
console.error('请求出错:', error);
});
在上面的例子中,第一个then通过response.ok判断请求是否成功,失败时抛出异常;随后调用response.json()将响应流解析为JavaScript对象。注意,response.json()本身返回的是Promise,所以需要继续使用then来获取最终数据。如果后端返回的不是JSON,可以改用response.text()等方法。
发起POST请求提交数据
fetch的第二个参数是一个配置对象,用于设置请求方法、请求头、请求体等。发送POST请求时,一般将method明确指定为'POST',并在headers中设置Content-Type为application/json,让服务器知道请求体是JSON格式。body字段需要传JSON字符串,因此使用JSON.stringify将对象序列化。
// 发起POST请求提交新用户信息
fetch('https://ipipp.com/api/users', {
method: 'POST', // 请求方法
headers: {
'Content-Type': 'application/json' // 设置请求体格式为JSON
},
body: JSON.stringify({ // 请求体数据,需要转为JSON字符串
name: '张三',
age: 25,
email: 'zhangsan@ipipp.com'
})
})
.then(response => {
if (!response.ok) {
throw new Error('提交失败');
}
return response.json();
})
.then(result => {
console.log('提交结果:', result);
})
.catch(error => {
console.error('提交出错:', error);
});
提交完成后,服务器通常会返回一个包含创建结果的对象,同样通过response.json()读取。值得注意的是,如果请求头设置了Content-Type,但body不是合法的JSON字符串,服务器可能返回400错误。因此在实际项目中,建议在发送前对数据进行校验,并在catch中提供相应的提示信息,以提升用户体验。
结合async/await优化异步代码
虽然fetch配合then链式调用已经能够表达异步逻辑,但在多个请求存在依赖关系时,then嵌套会明显增加代码的复杂度。async/await是ES2017引入的异步语法,它让异步代码看起来与同步代码几乎一样。在async函数中,使用await等待一个Promise的结果,如果Promise被reject,会自动抛出异常,可以通过try/catch捕获。
// 使用async/await封装fetch请求
async function getUserData() {
try {
const response = await fetch('https://ipipp.com/api/users/1');
if (!response.ok) {
throw new Error('请求失败,状态码:' + response.status);
}
const userData = await response.json();
console.log('用户详情:', userData);
return userData;
} catch (error) {
console.error('获取用户数据出错:', error);
throw error; // 可以选择将错误继续抛出给上层处理
}
}
// 调用封装好的函数
getUserData();
使用async/await后,请求的顺序、成功逻辑和错误处理都集中在一个函数中,可读性明显提升。其中throw error将错误重新抛出,便于上层调用方继续处理。如果需要并行请求多个互不依赖的接口,可以配合Promise.all一起使用,进一步提升请求效率。
常见注意事项与实践建议
在实际开发中,fetch有一些容易被忽略的细节,值得逐一整理。首先,fetch默认不会携带Cookie。在涉及用户登录态的场景中,如果后端依赖Session或Cookie进行身份认证,就必须在请求配置中将credentials设置为include,否则服务器会认为请求未授权。credentials可选值为omit、same-origin和include,分别对应不携带Cookie、同源携带和跨域携带。
其次,Response对象提供了多种解析方法。除了json()之外,text()适合解析纯文本,blob()适合解析图片或文件,formData()适合解析multipart/form-data响应。开发者应当根据后端实际返回的内容选择正确的方法,如果误用可能导致解析失败或数据丢失。
第三,当请求耗时过长,需要支持用户主动取消时,可以使用AbortController。AbortController通过signal向fetch传递取消信号,调用abort()后会中断请求,并触发一个名为AbortError的错误。在catch中判断error.name是否等于'AbortError',即可区分主动取消和其他异常。下面是一个完整的取消请求示例。
// 使用AbortController取消fetch请求
const controller = new AbortController();
const signal = controller.signal;
fetch('https://ipipp.com/api/long-request', { signal })
.then(response => response.json())
.then(data => console.log('请求结果:', data))
.catch(error => {
if (error.name === 'AbortError') {
console.log('请求已被取消');
} else {
console.error('请求出错:', error);
}
});
// 3秒后取消请求
setTimeout(() => {
controller.abort();
}, 3000);
通过上述几个方面的整理可以看出,fetch虽然不像一些第三方请求库那样拥有丰富的拦截器机制,但原生能力已经足够覆盖大多数异步数据获取场景。开发者只要理解Promise的基本语义,并处理好响应状态与异常分支,就能用fetch编写出稳定且易维护的网络请求代码。
fetch_API异步数据获取JavaScriptHTTP请求修改时间:2026-07-09 07:27:26