Skip to content

Instantly share code, notes, and snippets.

@webmaxru
Last active November 29, 2018 17:27
Show Gist options
  • Save webmaxru/dfdbb0ef02c22c39febf67b2c1b8b41a to your computer and use it in GitHub Desktop.
Save webmaxru/dfdbb0ef02c22c39febf67b2c1b8b41a to your computer and use it in GitHub Desktop.
Background Fetch. Step 3: Improving UX
<button id="bgFetchButton">Store assets locally</button>
<div id="progressStatus">Progress: waiting...</div>
<script>
bgFetchButton = document.querySelector('#bgFetchButton');
progressStatus = document.querySelector('#progressStatus');
bgFetchButton.addEventListener('click', async event => {
// Let's assume that we got some unique ID of the asset set we want to download
let assetToFetchId = 'series';
try {
bgFetchButton.disabled = true;
const registration = await navigator.serviceWorker.ready;
// This could be an API call to our backend
let assetsDataResponse = await fetch(
`/assets/${assetToFetchId}-data.json`
);
let assetsData = await assetsDataResponse.json();
const bgFetchRegistration = await registration.backgroundFetch.fetch(
assetToFetchId,
assetsData.urls,
{
icons: assetsData.icons,
title: `Downloading ${assetsData.title}`,
downloadTotal: assetsData.downloadTotal
}
);
bgFetchRegistration.addEventListener('progress', event => {
fetchProgress = event.currentTarget;
progressStatus.innerHTML = `Progress: downloaded ${bytesToSize(
fetchProgress.downloaded
)} from ${bytesToSize(fetchProgress.downloadTotal)} (${Math.round(
(fetchProgress.downloaded * 100) / fetchProgress.downloadTotal
)}%)`;
if (fetchProgress.downloadTotal==fetchProgress.downloaded) {
bgFetchButton.disabled = false;
}
});
} catch (err) {
alert(
'Please enable downloads for this website (click the icon on the right side of the address bar)'
);
console.error(err);
}
});
function bytesToSize(bytes, decimals) {
if (bytes == 0) return '0 Bytes';
var k = 1024,
dm = decimals <= 0 ? 0 : decimals || 2,
sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js');
});
}
</script>
{
"title": "My series",
"urls": ["/assets/s01e01.mpg", "/assets/s01e02.mpg"],
"downloadTotal": 1531774699,
"icons": [
{
"src": "icon.png",
"size": "128x128",
"type": "image/png"
}
]
}
addEventListener('backgroundfetchsuccess', event => {
console.log('[Service Worker]: Background Fetch Success', event.registration);
event.waitUntil(
(async function() {
try {
// Iterating the records to populate the cache
const cache = await caches.open(event.registration.id);
const records = await event.registration.matchAll();
const promises = records.map(async record => {
const response = await record.responseReady;
await cache.put(record.request, response);
});
await Promise.all(promises);
// [Optional] This could be an API call to our backend
let assetsDataResponse = await fetch(
`/assets/${event.registration.id}-data.json`
);
let assetsData = await assetsDataResponse.json();
// Updating UI
await event.updateUI({
title: `${assetsData.title} is ready`,
icons: assetsData.icons
});
} catch (err) {
await event.updateUI({
title: `${assetsData.title} failed: ${
event.registration.failureReason
}`
});
}
})()
);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment