In this post we will review a method of fetching the client URL in a ServiceWorker.
Note that I've already created a post for a ServiceWorker general concepts here.
To get the client, whose event the ServiceWorker is handling, the documentation informs us about the event.clientId API, and also about the clients.get API. However, the secret that is not told in the documentation, is that the API is async, while the ServiceWorker fetch event handler is synchronous.
The method to handle this, is by returning a promise in the event.respondWith API. In addition, to make sure the service worker is handling all clients, including the one it is activated from, use the clients.claim API.
So our final ServiceWorker looks as follows:
self.addEventListener('install', event => event.waitUntil(self.skipWaiting()))
self.addEventListener('activate', event => event.waitUntil(self.clients.claim()))
self.addEventListener('fetch', serviceWorkerListener)
function serviceWorkerListener(event) {
event.respondWith(serviceWorkerListenerAsync(event))
}
async function serviceWorkerListenerAsync(event) {
let clientUrl
if (event.clientId) {
const clients = await self.clients.matchAll({
includeUncontrolled: true,
type: 'window',
})
clients.forEach(client => {
if (client.id === event.clientId) {
clientUrl = client.url
}
})
}
return handleEvent(event, clientUrl)
}
Now we can implement the handleEvent function which receives the original event as well as the client URL.
Final Note
Using the method described above, the ServiceWorker can return different results for the same URL based on the client's location.url. This is a great method to add flexibility to your site.