Fetch API与XMLHttpRequest的比较
Fetch API与XMLHttpRequest的基本概念
Fetch API是现代浏览器提供的新标准,用于替代传统的XMLHttpRequest(XHR)进行网络请求。它基于Promise设计,语法更简洁直观。XMLHttpRequest则是早期浏览器提供的API,虽然功能强大但使用复杂。两者都能完成HTTP请求,但在实现方式和特性上有显著差异。
// Fetch API基本用法
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
// XMLHttpRequest基本用法
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data');
xhr.onload = function() {
if (xhr.status === 200) {
console.log(JSON.parse(xhr.responseText));
}
};
xhr.send();
语法与使用体验
Fetch API采用链式Promise调用,代码结构更扁平化。错误处理通过catch统一捕获,支持async/await语法糖。XMLHttpRequest则需要配置回调函数,容易产生"回调地狱"。
// Fetch的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('Fetch failed:', error);
}
}
// XHR的事件监听方式
const xhr = new XMLHttpRequest();
xhr.addEventListener('load', handleLoad);
xhr.addEventListener('error', handleError);
xhr.open('GET', 'https://api.example.com/data');
xhr.send();
function handleLoad() { /*...*/ }
function handleError() { /*...*/ }
请求与响应处理
Fetch API的Response对象提供了丰富的方法:
response.json()
解析JSONresponse.text()
获取文本response.blob()
处理二进制数据response.formData()
处理表单数据
XMLHttpRequest需要手动处理响应类型:
xhr.responseType = 'json'; // 或'text'、'arraybuffer'等
xhr.onload = function() {
console.log(xhr.response); // 根据responseType自动解析
};
错误处理机制
Fetch只在网络故障时reject,HTTP错误状态(如404)不会触发catch。需要额外检查response.ok或status。XMLHttpRequest通过status属性直接判断请求状态。
// Fetch的错误处理
fetch('https://api.example.com/404')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.catch(error => console.log('Error:', error.message));
// XHR的错误处理
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response);
} else {
console.error('Request failed with status:', xhr.status);
}
}
};
请求控制与超时
XMLHttpRequest原生支持timeout属性,而Fetch需要结合AbortController实现超时控制:
// Fetch超时控制
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000);
fetch('https://api.example.com/slow', {
signal: controller.signal
})
.then(response => {
clearTimeout(timeoutId);
return response.json();
})
.catch(error => {
if (error.name === 'AbortError') {
console.log('Request timed out');
}
});
// XHR超时设置
xhr.timeout = 5000;
xhr.ontimeout = function() {
console.log('Request timed out');
};
请求进度监控
XMLHttpRequest提供进度事件:
xhr.upload.onprogress = function(event) {
console.log(`Uploaded ${event.loaded} of ${event.total} bytes`);
};
xhr.onprogress = function(event) {
console.log(`Downloaded ${event.loaded} of ${event.total} bytes`);
};
Fetch API目前没有原生进度API,但可以通过响应体的流式处理模拟:
const response = await fetch('https://api.example.com/large-file');
const reader = response.body.getReader();
let receivedLength = 0;
while(true) {
const {done, value} = await reader.read();
if (done) break;
receivedLength += value.length;
console.log(`Received ${receivedLength} bytes`);
}
跨域请求处理
两者都遵循同源策略,但Fetch的CORS模式配置更明确:
fetch('https://api.example.com/data', {
mode: 'cors',
credentials: 'include' // 携带cookie
});
XMLHttpRequest需要设置withCredentials属性:
xhr.withCredentials = true;
浏览器兼容性
XMLHttpRequest兼容所有现代浏览器甚至IE6。Fetch API在IE完全不支持,但在现代浏览器中得到广泛实现。可以使用polyfill解决兼容问题:
<script src="https://cdn.jsdelivr.net/npm/whatwg-fetch@3.6.2/dist/fetch.umd.min.js"></script>
性能比较
在简单请求场景下两者性能差异不大。对于大量并发请求,Fetch可能略有优势,因为基于Promise的实现更轻量。XMLHttpRequest在需要精细控制请求过程时表现更好。
高级功能对比
Fetch API支持Service Worker拦截和修改请求:
// Service Worker中
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => response || fetch(event.request))
);
});
XMLHttpRequest支持同步请求(会阻塞UI线程):
xhr.open('GET', 'https://api.example.com/data', false); // 同步
xhr.send();
if (xhr.status === 200) {
console.log(xhr.responseText);
}
实际应用场景选择
对于简单REST API调用,优先使用Fetch API。需要上传进度监控或兼容旧浏览器时选择XMLHttpRequest。现代框架如axios实际上对两者都进行了封装,提供了更统一的接口。
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn