Keywords: Fetch API | Upload Progress Monitoring | Streams API | XMLHttpRequest | Cross-Browser Compatibility
Abstract: This article provides an in-depth analysis of the technical challenges in implementing upload progress indicators with the Fetch API, focusing on the current support status and limitations of the Streams API. It explains why Fetch API lacks native progress event support and details how to implement upload progress monitoring using TransformStream in Chrome, with complete code examples. The article also compares XMLHttpRequest as an alternative solution and discusses cross-browser compatibility issues. Finally, it explores future developments in progress monitoring for Fetch API, offering comprehensive technical guidance for developers.
Technical Background of Fetch API and Upload Progress Monitoring
The Fetch API, as a modern standard interface replacing XMLHttpRequest, offers a more streamlined approach to handling asynchronous requests. However, unlike XMLHttpRequest, Fetch API was not designed with native support for upload and download progress events. This design decision stems from Fetch API's underlying architecture, which is based on Promises and the Streams API, aiming to provide more efficient streaming data processing capabilities.
Current Support Status and Limitations of Streams API
According to the WHATWG specification, progress monitoring in Fetch API needs to be implemented through the Streams API. Specifically, developers can create a pass-through stream to monitor byte transmission. The core of this approach lies in using TransformStream to intercept and process data streams, thereby calculating the number of bytes transferred.
Currently, support for the Streams API in browsers is still evolving. Chrome browser has supported using ReadableStream as the body of Fetch requests since version 105, making upload progress monitoring possible. Here is an example code that works in Chrome:
async function uploadWithProgress(blob, url) {
const totalBytes = blob.size;
let bytesUploaded = 0;
const progressStream = new TransformStream({
transform(chunk, controller) {
controller.enqueue(chunk);
bytesUploaded += chunk.byteLength;
const progress = bytesUploaded / totalBytes;
console.log(`Upload progress: ${(progress * 100).toFixed(2)}%`);
}
});
const response = await fetch(url, {
method: "PUT",
headers: { "Content-Type": "application/octet-stream" },
body: blob.stream().pipeThrough(progressStream),
duplex: "half"
});
return response;
}
It is important to note that this implementation currently works only in Chrome browser. Other major browsers like Firefox and Safari do not yet fully support the integration of Streams API with Fetch. Additionally, even when using Chrome, the duplex: "half" parameter must be set in the request options.
XMLHttpRequest as a Reliable Alternative
For applications requiring cross-browser compatibility, XMLHttpRequest remains the most reliable option for implementing upload progress monitoring. XMLHttpRequest provides comprehensive progress event support, including the xhr.upload.onprogress event, which accurately tracks upload progress.
Here is an example of implementing upload progress monitoring with XMLHttpRequest:
function uploadWithXHR(blob, url, onProgress) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", (event) => {
if (event.lengthComputable) {
const progress = event.loaded / event.total;
onProgress(progress);
}
});
xhr.addEventListener("load", () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response);
} else {
reject(new Error(`Request failed: ${xhr.status}`));
}
});
xhr.addEventListener("error", () => reject(new Error("Network error")));
xhr.addEventListener("abort", () => reject(new Error("Request cancelled")));
xhr.open("PUT", url, true);
xhr.setRequestHeader("Content-Type", "application/octet-stream");
xhr.send(blob);
});
}
Technical Challenges and Future Prospects
Implementing progress monitoring in Fetch API faces several key technical challenges. First, redirect handling is a complex issue: when a request is redirected, data may need to be retransmitted, but the Streams API does not support stream restarting. This could lead to inaccurate progress calculations.
Second, security considerations are also important. Exposing redirect counts may pose security risks, as JavaScript previously could not detect redirect occurrences. Browser vendors need to balance feature implementation with security protection.
In the future, Fetch API may support progress monitoring in two ways: first, by further improving the implementation of Streams API to accurately reflect byte transmission progress; second, by introducing higher-level callback mechanisms, similar to XMLHttpRequest's event model. Regardless of the approach, current technical limitations and security issues need to be addressed.
Practical Recommendations and Conclusion
For projects requiring immediate implementation of upload progress monitoring, it is recommended to choose appropriate technical solutions based on the target browser environment:
- If targeting only Chrome browser, use Fetch implementation based on
TransformStream - If cross-browser compatibility is needed, XMLHttpRequest is the most reliable choice
- For projects using frameworks like React, consider using third-party libraries like axios, which provide more concise progress monitoring APIs
As web standards continue to evolve, support for progress monitoring in Fetch API will gradually improve. Developers should monitor WHATWG specifications and implementation progress in major browsers, adjusting technical solutions accordingly. At this stage, understanding the advantages and disadvantages of different solutions and making informed choices based on specific requirements is key to ensuring application stability and user experience.