Social Media Photo by Ricardo Gomez Angel on Unsplash
A tiny utility to asynchronously drive a namespace exposed through a Shared/Service/Worker:
- property access
- functions invokes
- instances creation ...
- ... and instances methods invokes, or properties access
Instances reflected on the client are automatically cleared up on the worker though a dedicated FinalizationRegistry.
It is also possible, since v0.5.0
, to use functions as arguments, although these are stored "forever", so use this feature with caution.
Bear in mind, the context is currently not propagated from the Worker, so if it's strictly needed, bind the listener before passing it as-is.
This module is a modern simplification of workway, heavily inspired by electroff, but also available for NodeJS too as a safer, lighter, and easier alternative.
This module works with latest browsers, as long as the following APIs are available:
The exported namespace provides a mechanism to await any part of it, including a top level addEventListener
and removeEventListener
, to allow listening to custom postMessage
notifications from the Service/Shared/Worker.
See worker.js to better understand how this works.
// client.js
import ProxiedWorker from 'https://unpkg.com/proxied-worker/client';
// point at the file that exports a namespace
const nmsp = ProxiedWorker('./worker.js');
// custom notifications from the Worker
nmsp.addEventListener('message', ({data: {action}}) => {
if (action === 'greetings')
console.log('Worker said hello 👋');
});
// v0.5.0+ use listenres like features
nmsp.on('listener', (action, type) => {
console.log(action, 'called with type', type);
});
// access its properties
console.log(await nmsp.test);
// or its helpers
console.log(await nmsp.sum(1, 2));
await nmsp.delayed();
// or create instances
const instance = await new nmsp.Class('🍻');
// and invoke their methods
console.log(await instance.sum(1, 2));
// - - - - - - - - - - - - - - - - - - - - - -
// worker.js
importScripts('https://unpkg.com/proxied-worker/server');
ProxiedWorker({
test: 'OK',
sum(a, b) {
return a + b;
},
on(type, callback) {
setTimeout(() => {
callback('Event', type);
});
},
async delayed() {
console.log('context', this.test);
postMessage({action: 'greetings'});
return await new Promise($ => setTimeout($, 500, Math.random()));
},
Class: class {
constructor(name) {
this.name = name;
}
sum(a, b) {
console.log(this.name, a, b);
return a + b;
}
}
});
Alternatively, if the browser supports workers as module:
// client.js
import ProxiedWorker from 'https://unpkg.com/proxied-worker/client';
const nmsp = ProxiedWorker('./worker.js', {type: 'module'});
// worker.js
import ProxiedWorker from 'https://unpkg.com/proxied-worker/module';
ProxiedWorker({
// ...
});
The ProxiedWorker
signature is similar to a Worker
one, plus an extra third argument that is the constructor to use.
In order to have a SharedWorker
, this code might be used:
// client.js
import ProxiedWorker from 'https://unpkg.com/proxied-worker/client';
const nmsp = ProxiedWorker('./shared-worker.js', {type: 'module'}, SharedWorker);
// shared-worker.js
import ProxiedWorker from 'https://unpkg.com/proxied-worker/module';
ProxiedWorker({
// ...
});
Similarly to a SharedWorker
, it is also possible to register and use a ServiceWorker
to compute heavy tasks.
// client.js
import ProxiedWorker from 'https://unpkg.com/proxied-worker/client';
const nmsp = ProxiedWorker('./service-worker.js', {scope: '/'}, ServiceWorker);
// service-worker.js
importScripts('https://unpkg.com/proxied-worker/server');
ProxiedWorker({
// ...
});