Skip to content

Instantly share code, notes, and snippets.

@ahankinson
Last active December 15, 2022 11:27
Show Gist options
  • Save ahankinson/c655dd35ed455c2b0139f3bd9f60e36c to your computer and use it in GitHub Desktop.
Save ahankinson/c655dd35ed455c2b0139f3bd9f60e36c to your computer and use it in GitHub Desktop.
Verovio Worker and WorkerProxy
let worker = new Worker("verovio-worker.js");
let verovio = new WorkerProxy(worker);
let setOptions = await verovio.setOptions({});
let loadSuccess = await verovio.loadData(somestring);
/**
* The Worker for Verovio
*/
class Deferred
{
public promise: Promise<unknown>;
public reject: ((reason?: any) => void) | undefined;
public resolve: ((value: (PromiseLike<unknown> | unknown)) => void) | undefined;
constructor()
{
// @ts-ignore
this.promise = new Promise((resolve, reject) =>
{
this.reject = reject;
this.resolve = resolve;
});
}
}
importScripts("https://www.verovio.org/javascript/develop/verovio-toolkit-wasm.js");
// importScripts("/dist/static/verovio-toolkit-wasm.js");
// Initializing an empty object to prevent if in onMessage listener the toolkit
// is being accessed before Module.onRuntimeInitialized
let verovioToolkit = {};
// Global deferred Promise that can be resolved when Module is initialized
const moduleIsReady = new Deferred();
// Create a new toolkit instance when Module is ready
// @ts-ignore
verovio.module.onRuntimeInitialized = function ()
{
// Set the global
// @ts-ignore
verovio.enableLog(verovio.LOG_ERROR);
// @ts-ignore
verovioToolkit = new verovio.toolkit();
postMessage({
method: "verovio-ready",
result: null,
});
};
// Listen to messages send to this worker
addEventListener("message", (event) =>
{
// Destruct properties passed to this message event
const {taskId, method, args} = event.data;
// Check if verovio toolkit has passed method
// @ts-ignore
const fn = verovioToolkit[method || null];
let result;
if (!fn)
{
postMessage({
taskId,
method,
result: null
});
}
else
{
// console.log("Verovio call", method, args);
// Always respond to worker calls with postMessage
// Call verovio toolkit method and pass arguments
result = fn.apply(verovioToolkit, args || []);
postMessage({
taskId,
method,
result,
});
}
}, false);
import { Deferred } from "./deferred.js";
let id: number = 1;
let callList: Map<number, Deferred> = new Map<number, Deferred>;
export class WorkerProxy
{
private worker: Worker;
constructor(worker: Worker)
{
this.worker = worker;
// Listen to response of the service worker
this.worker.addEventListener("message", (event) =>
{
const {taskId, result} = event.data;
// Check if there is a Deferred instance in workerTasks
const task: Deferred | undefined = callList.get(taskId);
if (task)
{
// If so resolve deferred promise and pass the returned value
// @ts-ignore
task.resolve(result);
// delete it from the list
callList.delete(taskId);
}
}, false);
// Return a Proxy so it is possible to catch all property and method or function calls of the worker
return new Proxy(this, {
get: (target, method) =>
{
return function ()
{
const taskId = id++;
const args = Array.prototype.slice.call(arguments);
// Post a message to service worker with UUID, method or function name of the worker and passed arguments
target.worker.postMessage({
taskId,
method,
args
});
// Create a new Deferred instance and store it in workerTasks HashMap
const deferred = new Deferred();
callList.set(taskId, deferred);
// Return the (currently still unresolved) Promise of the Deferred instance
return deferred.promise;
};
}
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment