web-worker-helper
Version:
Utilities for running tasks on worker threads
97 lines (96 loc) • 3.83 kB
JavaScript
import { assert } from '../utils/env-utils/assert';
import { getLoadableWorkerURL } from '../utils/worker-utils/get-loadable-worker-url';
import { getTransferList } from '../utils/worker-utils/get-transfer-list';
var NOOP = function () { };
/**
* Represents one worker thread
*/
var WorkerThread = /** @class */ (function () {
function WorkerThread(props) {
this.terminated = false;
this.loadableURL = '';
var name = props.name, source = props.source, url = props.url;
assert(source || url); // Either source or url must be defined
this.name = name;
this.source = source;
this.url = url;
this.onMessage = NOOP;
this.onError = function (error) { return console.log(error); };
this.worker = this.createBrowserWorker();
}
WorkerThread.isSupported = function () {
return typeof Worker !== 'undefined';
};
/**
* Terminate this worker thread
* @note Can free up significant memory
*/
WorkerThread.prototype.destroy = function () {
this.onMessage = NOOP;
this.onError = NOOP;
this.worker.terminate();
this.terminated = true;
};
Object.defineProperty(WorkerThread.prototype, "isRunning", {
get: function () {
// TODO: isRunning
return Boolean(this.onMessage);
},
enumerable: false,
configurable: true
});
/**
* Send a message to this worker thread
* @param data any data structure, ideally consisting mostly of transferrable objects
* @param transferList If not supplied, calculated automatically by traversing data
*/
WorkerThread.prototype.postMessage = function (data, transferList) {
transferList = transferList || getTransferList(data);
this.worker.postMessage(data, transferList);
};
/**
* Generate a standard Error from an ErrorEvent
* @param {ErrorEvent} event
*/
WorkerThread.prototype.getErrorFromErrorEvent = function (event) {
// Note Error object does not have the expected fields if loading failed completely
// https://developer.mozilla.org/en-US/docs/Web/API/Worker#Event_handlers
// https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent
var message = 'Failed to load ';
message += "worker ".concat(this.name, " from ").concat(this.url, ". ");
if (event.message) {
message += "".concat(event.message, " in ");
}
// const hasFilename = event.filename && !event.filename.startsWith('blob:');
// message += hasFilename ? event.filename : this.source.slice(0, 100);
if (event.lineno) {
message += ":".concat(event.lineno, ":").concat(event.colno);
}
return new Error(message);
};
/**
* Creates a worker thread on the browser
*/
WorkerThread.prototype.createBrowserWorker = function () {
var _this = this;
this.loadableURL = getLoadableWorkerURL({ source: this.source, url: this.url });
var worker = new Worker(this.loadableURL, { name: this.name });
worker.onmessage = function (event) {
if (!event.data) {
_this.onError(new Error('No data received'));
}
else {
_this.onMessage(event.data);
}
};
// This callback represents an uncaught exception in the worker thread
worker.onerror = function (error) {
_this.onError(_this.getErrorFromErrorEvent(error));
_this.terminated = true;
};
worker.onmessageerror = function (event) { return console.error("worker ".concat(_this.name, ", message error: ").concat(event)); };
return worker;
};
return WorkerThread;
}());
export default WorkerThread;