Demystifying Web Workers and Service Workers

@nolanlawson

hype train

@nolanlawson

photo of Nolan Lawson

http://edge.ms

edge.ms website

Why Web Workers?

Every line of frontend JS you've ever written has (momentarily) stopped your page from working.

60 frames per second (FPS)

1000ms / 60 frames = 16.7ms

Isn't asynchronicity enough?

// Everything between here...
$.getJSON('/payload.json', function (response) {
  // ... and here is free, right?
});

IndexedDB

(Yes, even though it's async)

XMLHttpRequest

(Yes, even async)

fetch

(Yes, even though it has response.json())

Stuff that blocks the DOM

  • IndexedDB
  • XHR
  • JSON.parse
  • fetch
  • Garbage collection
  • JavaScript!

WEB WORKERS!

// index.js

var worker = new Worker('worker.js');
worker.postMessage('ping');
worker.onmessage = function (e) {
  console.log(e.data); // 'pong'
};
// worker.js

self.onmessage = function (e) {
  console.log(e.data); // 'ping'
  self.postMessage('pong');
};
caniuse page for Web Workers

Who's using Web Workers?

Why Service Workers?

// index.js

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register(
            '/service-worker.js');
}
// service-worker.js

self.addEventListener('fetch',
    function (e) {
      e.respondWith(fetch(e.request));
    }
);
caniuse page for Service Workers
is service worker ready page
Web WorkersService Workers
Tab controlMany per tabOne for all tabs
LifespanSame as tabIndependent
Good forParallelismOffline

Protips

Beware of API support

  • No LocalStorage
  • No XHR in SW, only fetch()
  • No FileReader in Firefox <46
  • No IndexedDB in Safari <10
  • No console in Android <5
Functions and classes available to workers
html5workertest.com

html5workertest.com

promise-worker

// index.js
var pw = new PromiseWorker(
  new Worker('worker.js'));
pw.postMessage('yo').then(supports => {
  if (!supports) {
    // fall back to worker polyfill
  }
});
// worker.js
registerPromiseWorker(msg => {
  return !!self.indexedDB;
});

pseudo-worker

// index.js
var worker = new PseudoWorker(
  'worker.js');
var pm = new PromiseWorker(worker);
pm.postMessage('yo').then(msg => {
  // ...
});
// worker.js
registerPromiseWorker(msg => {
  // This will run on the main thread!
});

Powerful concepts for the web

  • Parallelism (Web Workers)
  • Offline (Service Workers)

Thank you!

@nolanlawson

nolanlawson.github.io/cascadia-2016