Comparison between Fetch API and XMLHttpRequest
Basic Concepts of Fetch API and XMLHttpRequest
The Fetch API is a modern browser standard designed to replace the traditional XMLHttpRequest (XHR) for network requests. It is based on Promises, offering a more concise and intuitive syntax. XMLHttpRequest, on the other hand, is an earlier browser API that, while powerful, is more complex to use. Both can perform HTTP requests but differ significantly in implementation and features.
// Basic usage of Fetch API
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
// Basic usage of 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();
Syntax and User Experience
The Fetch API uses chained Promise calls, resulting in flatter code structures. Error handling is unified through catch
and supports the async/await
syntax. XMLHttpRequest requires callback configuration, which can lead to "callback hell."
// Fetch with 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 with event listeners
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() { /*...*/ }
Request and Response Handling
The Fetch API's Response object provides rich methods:
response.json()
for JSON parsingresponse.text()
for textresponse.blob()
for binary dataresponse.formData()
for form data
XMLHttpRequest requires manual response type handling:
xhr.responseType = 'json'; // or 'text', 'arraybuffer', etc.
xhr.onload = function() {
console.log(xhr.response); // Automatically parsed based on responseType
};
Error Handling Mechanisms
Fetch only rejects on network failures; HTTP error statuses (e.g., 404) do not trigger catch
. Additional checks like response.ok
or status
are required. XMLHttpRequest directly checks the status
property for request states.
// Fetch error handling
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 error handling
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);
}
}
};
Request Control and Timeouts
XMLHttpRequest natively supports the timeout
property, while Fetch requires AbortController
for timeout control:
// Fetch timeout control
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 timeout setting
xhr.timeout = 5000;
xhr.ontimeout = function() {
console.log('Request timed out');
};
Request Progress Monitoring
XMLHttpRequest provides progress events:
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 currently lacks native progress APIs but can simulate it via streaming:
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`);
}
Cross-Origin Request Handling
Both follow the same-origin policy, but Fetch's CORS mode is more explicit:
fetch('https://api.example.com/data', {
mode: 'cors',
credentials: 'include' // Include cookies
});
XMLHttpRequest requires the withCredentials
property:
xhr.withCredentials = true;
Browser Compatibility
XMLHttpRequest is compatible with all modern browsers, including IE6. Fetch API is unsupported in IE but widely implemented in modern browsers. Polyfills can address compatibility:
<script src="https://cdn.jsdelivr.net/npm/whatwg-fetch@3.6.2/dist/fetch.umd.min.js"></script>
Performance Comparison
For simple requests, performance differences are minimal. For high concurrency, Fetch may have a slight edge due to its lighter Promise-based implementation. XMLHttpRequest excels in fine-grained request control.
Advanced Feature Comparison
Fetch API supports Service Worker request interception:
// In a Service Worker
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => response || fetch(event.request))
);
});
XMLHttpRequest supports synchronous requests (blocks UI thread):
xhr.open('GET', 'https://api.example.com/data', false); // Synchronous
xhr.send();
if (xhr.status === 200) {
console.log(xhr.responseText);
}
Practical Application Scenarios
For simple REST API calls, prefer Fetch API. Choose XMLHttpRequest for upload progress monitoring or legacy browser support. Modern libraries like axios encapsulate both, offering a unified interface.
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn