Service workers in Depth.

If you intend your web app to run offline, service workers are god-sent.

Onejohi
4 min readNov 13, 2018

A service worker is also known as a web worker. Service workers implement a simple way to run scripts in the background separating them from the main thread. This enables scripts to run efficiently without interfering with the UI. This article explains service workers in depth, if you wish to learn about creating an offline web app you can start here. Service workers are explained lightly at the end.

Once a service worker is created and registered, it can then exchange messages with scripts in the main thread where the messages transferred can be of different data types (except functions). There are a couple of ways to create a service worker, here’s the simplest.

let worker = new Worker('./sw.js')

You can also create a service worker dynamically from a string using the method URL.createObjectURL()

let workerstring = 'function sayHi() { console.log("Hello") }'
let blobURL = URL.createObjectURL(new Blob(
["(" + workerstring + ")"],
{ type: 'text/javascript' }
))
let webworker = new Worker(blobURL)

There are other ways to achieve this like using the method Function.toString() to replicate the same by converting a function into a string.

let workerfunc = function() {
console.log('do something')
}
let blobURL = URL.createObjectURL(new Blob(
["(" + workerfunc.toString() + ")"],
{ type: 'text/javascript' }
))
let webworker = new Worker(blobURL)

A service worker is an event-driven worker registered against an origin and a path. It takes the form of a JavaScript file that can control the web page/site it is associated with, intercepting and modifying navigation and resource requests, and caching resources in a very granular fashion to give you complete control over how your app behaves in certain situations (the most obvious one being when the network is not available.)

source: MDN

What you should know about service workers (web workers)

  1. A service worker has a lifecycle completely separate from your main application.
  2. It’s a programmable network proxy.
  3. It will be terminated when not in use and restarted when needed.
  4. It can’t access the DOM directly.
  5. Requires a secure protocol (HTTPS)

Registering a service worker.

//check if service worker is available
if('serviceWorker' in navigator) {
navigator.serviceWorker.register('./sw.js').then(reg => {
console.log('Successful. Scope: ' + req.scope)
}).catch(err => {
console.log('Error: ' + err)
})
}

Be sure you have a sw.js file to register your service worker. You can call the navigator.serviceWorker.register() method on every page load. If the service worker is already registered, the browser automatically provides you with the registered service worker. It’s noteworthy to remember the service worker scope is highly dependent on its location. If you create your service worker in a /js/sw.js folder, it can only intercept fetch requests for files that begin with /js/.

Communicating with a Service Worker.

Workers run in a separate thread meaning you can only communicate with them using the method postMessage(). In the lines of code below, I’ll show you how to pass a string to a web worker where the web worker splits the string into an array and returns the array to the main thread where it’s then displayed in the console. Here’s the code in the main script file.

//register service worker here.let worker = new Worker('./sw.js')worker.postMessage('My Name Is Onejohi')worker.addEventListener('message', e => {
console.log(e.data)
})

From the service worker in ./sw.js

self.addEventListener('message', e => {
let data = new Array(e.data.split(" "))
self.postMessage(data)
})

Simple, isn’t it?😃 Refresh your web app and your browser console should now look like this.

You can also listen for messages like so.

webworker.onmessage = e => {
console.log("Message from sw: " + e.data)
}

./sw.js

self.onmessage = e => {
console.log("Message from parent: " + e.data)
}

Once you’re done with a service worker, you should terminate it to free up resources on the clients PC.

webworker.terminate()

Cache population.

Once your service worker is registered, the browser will install it and then activate it. You should use this activation event to cache the assets required to run the application offline. Always form a habit of naming your caches in versions i.e ‘v1’ so that you can update the cache array. When the browser finds the name of the version to open is identical, it may not update the values of the cache array assets.

self.addEventListener('install', e => {
e.waitUntil(
caches.open('v1').then(cache => {
return chache.addAll([
'/css/styles.css',
'/js/scripts.js'
])
}) )
})

Dedicated workers vs Shared workers.

A dedicated worker is only accessible to the script that called it.

let worker = new Worker('./sw.js')
worker.addEventListener('message', msg => {
console.log("Random PIN: " + msg.data)
})
worker.postMessage([999,9999])

.

self.addEventListener('message', msg => {
let min = data[0]
let max = data[1]
return Math.floor(Math.random() * (max - min + 1) + min)
}
//return random number between ['min','max'] values in msg

The following code snippet will generate a random number between 999 and 9999 which makes it strictly a 4 digit number. You can use this example to generate random PIN numbers for SIM cards.

A shared worker, on the other hand, is accessible to multiple scripts hence the name “shared” 😉. In shared workers, communication between the parent script and the workers is done via the port object. An explicit port has to be opened for multiple parent scripts to communicate with the worker.

let worker = new SharedWorker('./shw.js')
worker.port.start()
worker.port.postMessage('Tony')

./shw.js

self.port.start()   //open the port
self.onconnect = e => {
let port = e.ports[0] //get the port
port.onmessage = e => {
console.log("Hello " + e.data)
}
}

Hope this article has helped you learn something, share it with your friends and leave a comment. For more articles like these, follow me. 😄

--

--

Onejohi

Creative 🚀 | Gamer 🎮 | Web & App developer 💻📱 | Graphics Designer 📏📝 | Entrepreneur 💶 | Cool AF 😎🤓 https://onejohi.com | WhatsApp +254727321766