Fetch 和 XHR(XMLHttpRequest)都是浏览器提供的用于在客户端与服务器之间进行异步网络请求的 API,它们是前端实现数据交互(如获取后端数据、提交表单等)的核心工具。下面详细介绍两者的特点、用法、区别及适用场景。
XHR 是最早出现的异步网络请求 API(1999 年由微软引入,后成为 W3C 标准),也是 AJAX(Asynchronous JavaScript and XML)技术的核心。尽管现在有更现代的 Fetch,但 XHR 仍被广泛使用(例如 jQuery 的 $.ajax 就是基于 XHR 封装的)。
XHR 的使用步骤通常包括:创建对象 → 配置请求 → 发送请求 → 监听响应。
// 1. 创建 XHR 对象
const xhr = new XMLHttpRequest();
// 2. 配置请求(方法、URL、是否异步)
xhr.open('GET', '<https://api.example.com/data>', true);
// 3. 设置请求头(可选,如 Content-Type)
xhr.setRequestHeader('Content-Type', 'application/json');
// 4. 监听响应状态变化
xhr.onreadystatechange = function() {
// readyState 表示请求状态:
// 0: 未初始化,1: 加载中,2: 已发送,3: 接收中,4: 完成
if (xhr.readyState === 4) {
// status 是 HTTP 状态码(200 表示成功)
if (xhr.status >= 200 && xhr.status < 300) {
// 响应数据(xhr.responseText 是字符串,需手动解析为 JSON 等)
const data = JSON.parse(xhr.responseText);
console.log('请求成功:', data);
} else {
console.error('请求失败:', xhr.statusText);
}
}
};
// 5. 发送请求(POST 等带数据的请求需传入数据)
xhr.send(); // GET 请求无需参数,POST 可传 JSON.stringify(data)
onreadystatechange、onload、onerror 等事件监听状态。open 方法的第三个参数为 false 时,请求会阻塞 JS 执行(不推荐,影响用户体验)。xhr.abort() 取消正在进行的请求。progress 事件,可监听上传/下载进度(xhr.upload.onprogress)。ActiveXObject)。Fetch 是 ES6 后推出的现代网络请求 API(2015 年标准化),设计初衷是替代 XHR,语法更简洁,基于 Promise,支持异步/await,更符合现代 JS 异步编程风格。
Fetch 返回一个 Promise 对象,通过链式调用 then 处理响应,或用 async/await 简化代码。
// 1. 发送 GET 请求
fetch('<https://api.example.com/data>')
.then(response => {
// 1. 先判断 HTTP 状态码(Fetch 不会因 4xx/5xx 状态码 reject)
if (!response.ok) {
throw new Error(`HTTP 错误:${response.status}`);
}
// 2. 解析响应格式(response.json() 返回 Promise)
return response.json();
})
.then(data => {
console.log('请求成功:', data);
})
.catch(error => {
console.error('请求失败:', error);
});
// 用 async/await 简化(更推荐)
async function fetchData() {
try {
const response = await fetch('<https://api.example.com/data>');
if (!response.ok) throw new Error(`状态码:${response.status}`);
const data = await response.json();
console.log('请求成功:', data);
} catch (error) {
console.error('请求失败:', error);
}
}
fetchData();
fetch('<https://api.example.com/submit>', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: '张三', age: 20 }), // 需序列化
})
.then(response => response.json())
.then(data => console.log('提交成功:', data));