UNPKG

workerable

Version:

A wrapper around SharedWorker to provide a single synced store between browser tabs or windows

68 lines (55 loc) 2.59 kB
'use strict'; var workerUrl = "data:application/javascript;base64,Y29uc3QgcG9ydHMgPSBuZXcgU2V0KCk7CmxldCBkYXRhID0gbnVsbDsKCmZ1bmN0aW9uIGJyb2FkY2FzdEFsbCh0eXBlLCBkYXRhKSB7CiAgcG9ydHMuZm9yRWFjaChwb3J0ID0+IHsKICAgIHBvcnQucG9zdE1lc3NhZ2UoW3R5cGUsIGRhdGFdKTsKICB9KTsKfQoKZnVuY3Rpb24gYnJvYWRjYXN0T3RoZXIodGhpc1BvcnQsIHR5cGUsIGRhdGEpIHsKICBwb3J0cy5mb3JFYWNoKHBvcnQgPT4gewogICAgaWYgKHBvcnQgPT09IHRoaXNQb3J0KSByZXR1cm47CiAgICBwb3J0LnBvc3RNZXNzYWdlKFt0eXBlLCBkYXRhXSk7CiAgfSk7Cn0KCmZ1bmN0aW9uIG1zZ0hhbmRsZXIoZSkgewogIGNvbnN0IFt0eXBlLCBfZGF0YV0gPSBlLmRhdGE7CiAgc3dpdGNoICh0eXBlKSB7CiAgICBjYXNlICdzZXQnOgogICAgICBkYXRhID0gX2RhdGE7CiAgICAgIGJyb2FkY2FzdE90aGVyKHRoaXMsICdzZXQnLCBkYXRhKTsKICAgICAgYnJlYWs7CiAgICBjYXNlICdpbml0JzoKICAgICAgaWYgKHBvcnRzLnNpemUgPT09IDApIHsKICAgICAgICBkYXRhID0gX2RhdGE7CiAgICAgIH0KICAgICAgYnJlYWs7CiAgICBjYXNlICdjbG9zZSc6CiAgICAgIHBvcnRzLmRlbGV0ZSh0aGlzKTsKICAgICAgYnJlYWs7CiAgICBkZWZhdWx0OgogICAgICByZXR1cm47CiAgfQp9CgpzZWxmLmFkZEV2ZW50TGlzdGVuZXIoJ2Nvbm5lY3QnLCBmdW5jdGlvbihlKSB7CiAgaWYgKCFlLnBvcnRzIHx8ICFlLnBvcnRzLmxlbmd0aCkgcmV0dXJuOwogIGNvbnN0IHBvcnQgPSBlLnBvcnRzWzBdOwogIHBvcnQuc3RhcnQoKTsKICBwb3J0LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBtc2dIYW5kbGVyKTsKICBwb3J0cy5hZGQocG9ydCk7CiAgaWYgKHBvcnRzLnNpemUgPiAxKSB7CiAgICBwb3J0LnBvc3RNZXNzYWdlKFsnc2V0JywgZGF0YV0pOwogIH0KfSk7Cg=="; 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 }; } module.exports = sharedWritable;