workerable
Version:
A wrapper around SharedWorker to provide a single synced store between browser tabs or windows
64 lines (53 loc) • 1.32 kB
JavaScript
import workerUrl from './shared-worker.js';
export default function sharedWritable(init, startTrigger) {
const worker = new SharedWorker(workerUrl);
worker.port.start();
worker.port.postMessage(['init', init]);
worker.port.addEventListener('message', messageHandler);
const subs = new Set();
let stopTrigger = null;
let data = init;
function notifyAll() {
subs.forEach(cb => {
cb(data);
});
}
function subscribe(callback) {
callback(data);
subs.add(callback);
if (subs.size === 1 && typeof startTrigger === 'function') {
stopTrigger = startTrigger(set);
}
return () => {
subs.delete(callback);
if (subs.size === 0 && typeof stopTrigger === 'function') {
stopTrigger();
worker.port.postMessage(['close']);
}
};
}
function set(_data) {
if (_data === data) return;
data = _data;
worker.port.postMessage(['set', data]);
notifyAll();
}
function update(callback) {
const newData = callback(data);
if (newData === data) return;
data = newData;
worker.port.postMessage(['set', data]);
notifyAll();
}
function messageHandler(e) {
const [type, _data] = e.data;
if (type === 'set') {
set(_data);
}
}
return {
subscribe,
set,
update
};
}