proxied-worker
Version:
A tiny utility to asynchronously drive a namespace exposed through a Shared/Service/Worker
154 lines (110 loc) • 4.55 kB
Markdown
# proxied-worker
<sup>**Social Media Photo by [Ricardo Gomez Angel](https://unsplash.com/@ripato) on [Unsplash](https://unsplash.com/)**</sup>
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.
### Related + NodeJS
This module is a modern simplification of [workway](https://github.com/WebReflection/workway#readme), heavily inspired by [electroff](https://github.com/WebReflection/electroff#readme), but also **[available for NodeJS too](https://github.com/WebReflection/proxied-node#readme)** as a safer, lighter, and easier alternative.
## Compatibility / Requirements
This module works with latest browsers, as long as the following APIs are available:
* [FinalizationRegistry](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry)
* [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)
* [Worker](https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker)
**[Live Demo](https://webreflection.github.io/proxied-worker/test/)**
## API
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](./test/worker.js) to better understand how this works.
## Example
```js
// 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:
```js
// 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({
// ...
});
```
## As SharedWorker
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:
```js
// 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({
// ...
});
```
## As ServiceWorker
Similarly to a `SharedWorker`, it is also possible to register and use a `ServiceWorker` to compute heavy tasks.
```js
// 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({
// ...
});
```