UNPKG

@zlepper/rpc

Version:

Allows RPC from the main thread to a background worker thread (Of any kind), using ES6 classes.

101 lines 3.25 kB
// @ts-ignore function isEventDispatcher(target) { return '__initializeEventDispatcher' in target; } class WorkerProvider { target; serverConnection; constructor(target, serverConnection) { this.target = target; this.serverConnection = serverConnection; if (isEventDispatcher(target)) { target.__initializeEventDispatcher(this); } } stop() { this.serverConnection.removeListener(); } start() { this.serverConnection.addListener(data => this.handleInvocation(data)); } sendErrorResponse(invocation, error) { const errorMessage = { kind: 'message', refId: invocation.refId, success: false, error, }; // Not entirely sure why typescript confuses the overload here, but i'm not going to think too much about it // this specific part is never exposed to the end consumer, so it should be safe to just "ignore" this.serverConnection.send(errorMessage); } sendSuccessResponse(invocation, result) { const message = { kind: 'message', refId: invocation.refId, result, success: true, }; this.serverConnection.send(message); } sendEvent(type, data) { const event = { refId: -1, kind: 'event', type, data }; this.serverConnection.send(event); } handleInvocation(invocation) { try { const prop = this.target[invocation.propertyName]; if (typeof prop !== 'function') { this.sendErrorResponse(invocation, new Error(`Property ${String(invocation.propertyName)} is not a function on the underlying worker objects. Did you use the correct type in both the Worker and main code?`)); return; } const result = prop.apply(this.target, invocation.args); Promise.resolve(result) .then(response => { this.sendSuccessResponse(invocation, response); }) .catch(error => { this.sendErrorResponse(invocation, error); }); } catch (e) { this.sendErrorResponse(invocation, e); } } } export function startWorkerProvider(target, serverConnection) { const provider = createWorkerProvider(target, serverConnection); provider.start(); return provider; } export function createWorkerProvider(target, serverConnection) { return new WorkerProvider(target, serverConnection); } export class EventDispatcher { /** * @private */ ___typescriptInferenceHack = null; /** * @internal */ __workerProvider = null; /** * @internal */ __initializeEventDispatcher(provider) { this.__workerProvider = provider; } dispatchEvent(type, data) { if (!this.__workerProvider) { throw new Error('Worker provider has not been initialized. Did you call dispatchEvent before passing the worker to the provider?'); } this.__workerProvider.sendEvent(type, data); } } //# sourceMappingURL=worker-provider.js.map