Skip to content

Commit

Permalink
Bug fixes for Service Worker
Browse files Browse the repository at this point in the history
  • Loading branch information
pazaan committed Sep 9, 2020
1 parent 108764b commit 44cf70d
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 81 deletions.
26 changes: 4 additions & 22 deletions views/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -729,29 +729,11 @@
console.log('Service worker registered');
reg.addEventListener('updatefound', () => {
console.log('Service worker update detected');
reg.update();
const newWorker = reg.installing;
var reloaded;

newWorker.addEventListener('statechange', (stateEvent) => {
console.log('New worker state change', stateEvent.currentTarget.state, stateEvent);

if (stateEvent.currentTarget.state == 'installed') {
// `controller` should be assigned if an active worker already exists
if (navigator.serviceWorker.controller) {
// a new worker was activated, so refresh the page
if (reloaded) {
// needed to prevent reload loops with `update on reload` option in dev tools
return;
}

console.log('New service worker installed, refreshing');
reloaded = true;
window.location.reload(true);
} else {
// there was no active worker, so it was cached and no refresh is necessary
console.log('Service worker cached');
}
}
newWorker.addEventListener('statechange', (state) => {
console.log('New worker state change', state);
window.location.reload(true);
});
});
}).catch(function(error) {
Expand Down
149 changes: 90 additions & 59 deletions views/service-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,57 @@ const CACHE_LIST = [
'/images/logo2.png'
];

// Open a cache and use `addAll()` with an array of assets to add all of them
// to the cache. Return a promise resolving when all the assets are added.
function returnRangeRequest(request) {
return caches
.open(CACHE)
.then((cache) => {
return cache.match(request.url);
})
.then((res) => {
if (!res) {
return fetch(request)
.then(res => {
const clonedRes = res.clone();
return caches
.open(CACHE)
.then(cache => cache.put(request, clonedRes))
.then(() => res);
})
.then(res => {
return res.arrayBuffer();
});
}
return res.arrayBuffer();
})
.then((arrayBuffer) => {
const bytes = /^bytes=(\d+)-(\d+)?$/g.exec(
request.headers.get('range')
);
if (bytes) {
const start = Number(bytes[1]);
const end = Number(bytes[2]) || arrayBuffer.byteLength - 1;
return new Response(arrayBuffer.slice(start, end + 1), {
status: 206,
statusText: 'Partial Content',
headers: [
['Content-Range', `bytes ${start}-${end}/${arrayBuffer.byteLength}`]
]
});
} else {
return new Response(null, {
status: 416,
statusText: 'Range Not Satisfiable',
headers: [['Content-Range', `*/${arrayBuffer.byteLength}`]]
});
}
});
}

// Open a cache and `put()` the assets to the cache.
// Return a promise resolving when all the assets are added.
function precache() {
return caches.open(CACHE).then(function (cache) {
return caches.open(CACHE)
.then((cache) => {
// if any cache requests fail, don't interrupt other requests in progress
return Promise.allSettled(
CACHE_LIST.map((url) => {
Expand All @@ -59,89 +106,73 @@ function precache() {
});
}

// Open the cache where the assets were stored and search for the requested
// resource. Notice that in case of no matching, the promise still resolves
// but it does with `undefined` as value.
function fromCache(request) {
return caches.open(CACHE).then(function (cache) {
return cache.match(request).then(function (matching) {
return matching || Promise.reject('no-match');
});
});
}

// Update consists in opening the cache, performing a network request and
// storing the new response data.
function update(request) {
return caches.open(CACHE).then(function (cache) {
return fetch(request).then(function (response) {
return cache.put(request, response);
});
});
}

// Try to read the requested resource from cache.
// If the requested resource does not exist in the cache, fetch it from
// network and cache the response.
function fromCacheOrUpdate(request) {
return caches.open(CACHE).then(function (cache) {
return cache.match(request).then(function (cacheResponse) {
return cacheResponse || fetch(request).then(function (netResponse) {
cache.put(request, netResponse.clone());
return netResponse;
function fromCache(request) {
return caches.open(CACHE).then((cache) => {
return cache.match(request).then((matching) => {
console.log(matching);
if(matching){
return matching;
}

return fetch(request).then((response) => {
// console.log('Response from network is:', response);
cache.put(request, response.clone());
return response;
}).catch((error) => {
// This catch() will handle exceptions thrown from the fetch() operation.
// Note that a HTTP error response (e.g. 404) will NOT trigger an exception.
// It will return a normal response object that has the appropriate error code set.
console.error('Fetching failed:', error);

throw error;
});
});
});
}

// On install, cache some resources.
self.addEventListener('install', function(evt) {
console.log('The service worker is being installed.');
self.addEventListener('install', (evt) => {
// console.log('The service worker is being installed.');
self.skipWaiting();
evt.waitUntil(precache());
});

function inCache(request) {
let found = false;
CACHE_LIST.forEach( function (e) {
CACHE_LIST.forEach((e) => {
if (request.url.endsWith(e)) {
found = true;
}
});
return found;
}

self.addEventListener('fetch', function(evt) {
self.addEventListener('fetch', (evt) => {
if (!evt.request.url.startsWith(self.location.origin) || CACHE === 'developmentMode' || !inCache(evt.request) || evt.request.method !== 'GET') {
// console.log('Skipping cache for', evt.request.url);
evt.respondWith(fetch(evt.request));
//console.log('Skipping cache for ', evt.request.url);
return void evt.respondWith(fetch(evt.request));
}
if (evt.request.headers.get('range')) {
evt.respondWith(returnRangeRequest(evt.request));
} else {
var request = evt.request;
if (evt.request.headers.has('Range')) {
// Firefox will give an error if it tries to store partial content (206) responses in the cache.
// To mitigate this, strip the `Range` header from the request so a full document (200) is returned.
var strippedHeaders = new Headers(evt.request.headers).delete('Range');
request = new Request(evt.request, { headers: strippedHeaders });
}
// console.log('Using cache for', evt.request);
evt.respondWith(fromCacheOrUpdate(request));
evt.respondWith(fromCache(evt.request));
}
});

self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((cacheNames) => {
if (!cacheNames) {
// Fallback to an empty array if cache is empty.
// This can occur if the prefetch fails.
return [];
}
return Promise.all(
cacheNames.map((cacheName) => {
if (cacheName !== CACHE) {
// console.log('Deleting out of date cache:', cacheName);
return caches.delete(cacheName);
}
})
);
}));

return cacheNames.filter((cacheName) => CACHE !== cacheName);
}).then((unusedCaches) => {
// console.log('DESTROYING CACHE', unusedCaches.join(','));
return Promise.all(unusedCaches.map((unusedCache) => {
return caches.delete(unusedCache);
}));
}).then(() => self.clients.claim())
);
});
});

0 comments on commit 44cf70d

Please sign in to comment.