Javascript Fetch: download progress

In modern web development, efficiently handling HTTP requests is paramount. The Fetch API has become the go-to solution for making network requests in JavaScript. This article delves into mastering the Fetch API, focusing on how to track download progress. We will explore various methods, provide real-world code examples, and share professional tips to enhance your understanding and implementation of the Fetch API.

Tracking Download Progress

One of the advanced features of the Fetch API is the ability to track the progress of a download. This is particularly useful for large files or when providing user feedback during lengthy operations.

Using Readable Streams

To track download progress, we can utilize the ReadableStream interface. This allows us to read the response body in chunks and monitor the progress.

async function fetchWithProgress(url, onProgress, size) { const response = await fetch(url); const reader = response.body.getReader(); let receivedLength = 0; const chunks = []; while (true) { const { done, value } = await reader.read(); if (done) { break; } chunks.push(value); receivedLength += value.length; onProgress(receivedLength, size); } const chunksAll = new Uint8Array(receivedLength); let position = 0; for (let chunk of chunks) { chunksAll.set(chunk, position); position += chunk.length; } const result = new TextDecoder("utf-8").decode(chunksAll); return result; } function onProgress(received, total) { const percent = Math.round(100*received/total) console.log(`received ${received} Bytes out of ${total} Bytes ${percent}%`); } const url = 'https://www.w3docs.com/uploads/media/default/0001/05/dd10c28a7052fb6d2ff13bc403842b797a73ff3b.txt'; const size = 3_900_000; // it's 3.72 MB fetchWithProgress(url, onProgress, size)

The function fetchWithProgress fetches data from a specified URL and tracks the download progress. It reads the response body in chunks using the ReadableStream interface and calls the onProgress callback with the received length and total content length. The downloaded data is then reconstructed from the chunks and returned as a decoded string.

Displaying Progress to Users

To provide feedback to users, we can integrate a progress bar that updates as the download progresses.

<body>
  <div id="progress-bar" style="width: 100%; background-color: #e0e0e0;">
    <div id="progress" style="width: 0; height: 20px; background-color: #76c7c0;"></div>
  </div>
  <div id="output"></div>
  <script>
    function updateProgressBar(received, total) {
      const progressElement = document.getElementById('progress');
      const percentage = (received / total) * 100;
      progressElement.style.width = percentage + '%';
      alert('Percentage updated! Look at the progress bar. It\'s ' + percentage + '%');
    }
    document.addEventListener('DOMContentLoaded', () => {
      const url = 'https://www.w3docs.com/uploads/media/default/0001/05/dd10c28a7052fb6d2ff13bc403842b797a73ff3b.txt';
      const size = 3_900_000; // it's 3.72 MB
      fetchWithProgress(url, updateProgressBar, size)
      .then(data => {
        document.getElementById('output').textContent = 'File content: ' + data.slice(0, 1000) + '...';
      });
    });
    async function fetchWithProgress(url, onProgress, size) {
      const response = await fetch(url);
      const reader = response.body.getReader();
      let receivedLength = 0;
      const chunks = [];
      while (true) {
        const { done, value } = await reader.read();
        if (done) {
          break;
        }
        chunks.push(value);
        receivedLength += value.length;
        onProgress(receivedLength, size);
      }
      const chunksAll = new Uint8Array(receivedLength);
      let position = 0;
      for (let chunk of chunks) {
        chunksAll.set(chunk, position);
        position += chunk.length;
      }
      const result = new TextDecoder("utf-8").decode(chunksAll);
      return result;
    }
  </script>
</body>
If you are downloading a very large file, avoid updating the UI too frequently. For example, instead of updating the progress bar for every single chunk, you can update it less frequently (e.g., every few chunks or based on a time interval). It helps keeping your UI lightweight.

The HTML elements in the example above sets up a progress bar to visualize the download progress and a preformatted text area to display the downloaded content. The progress-bar div serves as the container, and the progress div represents the actual progress of the download.

The JavaScript code updates the progress bar based on the received data length and total content length. The updateProgressBar function calculates the percentage of downloaded data and adjusts the width of the progress bar accordingly. The event listener triggers the fetchWithProgress function on page load, updating the progress bar and displaying the downloaded content in the output element.

Professional Tips

  • Use ReadableStreams Wisely: While powerful, using ReadableStreams can be complex. Ensure proper error handling and memory management to avoid potential issues.
  • Optimize User Feedback: Providing real-time feedback on download progress improves user satisfaction and can make your application feel more responsive.
  • Leverage Browser Capabilities: Different browsers may have varying support for advanced features. Test your implementation across multiple browsers to ensure compatibility.

With these insights and examples, you are now equipped to implement the Fetch API with download progress tracking in your projects, offering users a seamless and informative experience.

Conclusion

Mastering the Fetch API involves understanding not only how to make basic requests but also how to handle more advanced scenarios such as tracking download progress. By using ReadableStreams, we can monitor and provide feedback on downloads, significantly enhancing the user experience. Implementing these techniques will ensure your applications are robust, user-friendly, and capable of handling large data transfers efficiently.

Practice Your Knowledge

What are the key steps to track download progress using the Fetch API?

Quiz Time: Test Your Skills!

Ready to challenge what you've learned? Dive into our interactive quizzes for a deeper understanding and a fun way to reinforce your knowledge.

Do you find this helpful?