My service worker has a variable to store a secured hash, and injects it into headers for relevant HTTP requests, server app will then compare with its own to make it a secured login.
The hash is generated dynamically behind (in browser class using c# dotnet in my case).
Previously I always called postmessage on page loaded from browser to update the hash into sw. But encountered an issue that with 5-6 min inactive (without opening devtools), once click the button on page, sw is re-initialised or wake up with empty hash value, thus responding with empty value and failed the validation.
So I added a trigger from sw, but then encountered the race condition between message listener and fetch listener. I need the message listener to update the hash in sw, but fetch listener reposonded at same time. Seems timeout delay is not working.
console.log('top root log');
if (!self.secureHeader) {
self.secureHeader = 'Empty';
console.log('Refreshing header');
// this is my trigger when sw re-init
postMessage({ type: 'refreshHeader', msg: '' }, '*');
//// this is a bad attempt which didn't block the listener
// setTimeout(function() {
// console.log('timeout ended');
// }, 50);
}
self.addEventListener('message', function (event) {
if (event.data.type == 'setHeader') {
self.secureHeader = event.data.msg;
console.log('Header received:'+ self.secureHeader);
}
}, false);
self.addEventListener('fetch', function(e) {
console.log(Responding: ${self.secureHeader});
////I tried timeout here, error: The event handler is already finished.
//if (self.secureHeader === 'Empty')
//timeout to do respond
e.respondWith(
fetch(request, {
headers: getSecureHeaders(request)
})
.catch(() => {
return caches.match(request);
})
);
});
From my testing, after a few minutes waiting and sw expiry,
The logs appear to be:
(sw wake up) top root logs appear.
"Refreshing header" triggered.
fetch event started.
Then "Header received" and "Responding…" comes at the same time,
how can I properly chain them? Any advice, thanks.
2
Answers
Workout with a lazy way and another elegant way using Promise.
1. Add a delay inside respondWith
2. chain promises to respond
Creating a timeout won’t stop the fetch event handler. You need a promise that you can wait for before making the
fetch()
request. You can initialise that promise when asking for the refreshed header: