UNPKG

@soapbox.pub/wasmboy

Version:

Soapbox fork of Wasmboy.

112 lines (94 loc) 2.9 kB
// Smarter workers. // Workers with ids, pub sub, etc... // https://medium.com/dailyjs/threads-in-node-10-5-0-a-practical-intro-3b85a0a3c953 import { getEventData, readBase64String } from './util'; // Generate ids. Use a counter to help against possible collisions. let idCounter = 0; const generateId = () => { const randomId = Math.random() .toString(36) .replace(/[^a-z]+/g, '') .substr(2, 10); idCounter++; const id = `${randomId}-${idCounter}`; if (idCounter > 100000) { idCounter = 0; } return id; }; export function getSmartWorkerMessage(message, messageId, workerId) { if (!messageId) { messageId = generateId(); } return { workerId, messageId, message }; } export class SmartWorker { constructor(worker, id) { this.id = generateId(); if (id) { this.id = id; } this.messageListeners = []; this.worker = worker; this.worker.onmessage = this._onMessageHandler.bind(this); } postMessageIgnoreResponse(message, transfer) { const messageObject = getSmartWorkerMessage(message, undefined, this.id); this.worker.postMessage(messageObject, transfer); } postMessage(message, transfer, timeout) { if (!timeout) { timeout = 1000; } const messageObject = getSmartWorkerMessage(message, undefined, this.id); const messageId = messageObject.messageId; const messageIdListener = new Promise((resolve, reject) => { // Set a timeout before killing the message listener let messageDroppedTimeout = setTimeout(() => { console.warn('Message dropped', message); this.removeMessageListener(messageId); reject(); }, timeout); // Listen for a message with the same message id to be returned this.addMessageListener((responseMessage, messageListener) => { const eventData = getEventData(responseMessage); if (eventData.messageId === messageId) { clearTimeout(messageDroppedTimeout); messageDroppedTimeout = undefined; this.removeMessageListener(messageListener.id); resolve(eventData); } }); }); this.worker.postMessage(messageObject, transfer); return messageIdListener; } addMessageListener(callback) { this.messageListeners.push({ id: generateId(), callback: callback }); } removeMessageListener(id) { let messageListenerIndex; this.messageListeners.some((messageListener, index) => { if (messageListener.id === id) { messageListenerIndex = index; return true; } return false; }); if (messageListenerIndex !== undefined) { this.messageListeners.splice(messageListenerIndex, 1); } } _onMessageHandler(message) { this.messageListeners.forEach(messageListener => { messageListener.callback(message, messageListener); }); } }