fetch-progress-indicators
fetch-progress-indicators copied to clipboard
Simpler solution for fetch-basic
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 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.