fetch-progress-indicators icon indicating copy to clipboard operation
fetch-progress-indicators copied to clipboard

Simpler solution for fetch-basic

Open tkrotoff opened this issue 3 years ago • 1 comments

In your fetch-basic example you read the response then "pipe" it to a new response:

...
return new Response(
    new ReadableStream({
      start(controller) {
        const reader = response.body.getReader();

        read();
        function read() {
          reader.read().then(({done, value}) => {
            if (done) {
              controller.close();
              return; 
            }
            loaded += value.byteLength;
            progress({loaded, total})
            controller.enqueue(value);
            read();
          }).catch(error => {
            console.error(error);
            controller.error(error)                  
          })
        }
      }
    })
  );
})
.then(response => response.blob())
.then(data => {
  status('download completed')
  document.getElementById('img').src = URL.createObjectURL(data);
})
...

There is no need to perform this extra work:

const content = []; // <===
let bytesReceived = 0;

while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  content.push(value); // <===
  bytesReceived += value.byteLength;
}

document.getElementById('img').src = URL.createObjectURL(new Blob(content));

Full example:

const progressIndicator = document.getElementById('progress');

const { headers, body } = await fetch(
  'https://fetch-progress.anthum.com/30kbps/images/sunrise-baseline.jpg'
);

const contentLength = headers.get('Content-Length');
if (contentLength === null) throw new Error('No Content-Length response header');
const totalBytes = parseInt(contentLength, 10);
progressIndicator.max = totalBytes;

if (body === null) throw new Error('No response body');
const reader = body.getReader();

const content = []; // <===
let bytesReceived = 0;

while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  content.push(value); // <===
  bytesReceived += value.byteLength;

  progressIndicator.value = bytesReceived;
}

document.getElementById('img').src = URL.createObjectURL(new Blob(content));
<progress id="progress" value="0"></progress>
<img id="img" alt="download-progress-img" src="data:,">

tkrotoff avatar Nov 02 '20 08:11 tkrotoff

@tkrotoff thanks for reaching out. I won't be able to look at this this week, but please ensure that browser compatibility isn't affected since the time this was originally released. If that's a non-issue, happy to revise.

anthumchris avatar Nov 02 '20 19:11 anthumchris