Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dfkaye/8757576315b1e00252b682dc785d584b to your computer and use it in GitHub Desktop.
Save dfkaye/8757576315b1e00252b682dc785d584b to your computer and use it in GitHub Desktop.
Misconceptions about structured clone data and terminating workers
// 7 June 2022
// Misconceptions about structured clone data and terminating workers.
// Messages to workers and channels do *not* need to be objects.
// They can be any primitive type that passes the structured
// cloning algorithm. Functions, DOM nodes, Symbols, Worker instances, etc.,
// are not cloned and will result in DOMExceptions.
// When terminating workers, it's best not to do that until a response has
// returned to the main or UI thread, or if you're cloning an invalid value
// in a try-catch construct.
// Terminating should really happen in a message handler, or inside the worker
// receiving a terminate or close command.
// See " close web workers by sending a command or action in the message" gist at
// https://gist.github.com/dfkaye/197f15f2811a3b90b536e943cd508c67
var script = `
// A local response value.
var response = "Worker says:";
// Handle message as a request.
onmessage = function(request) {
var value = request.data;
var type = typeof value;
// Send response.
postMessage([response, "type of ", value, "is", type])
}
`;
var blob = new Blob([script], {type: 'text/javascript'});
var url = window.URL.createObjectURL(blob);
var worker = new Worker(url);
// Receive messages from the worker.
worker.onmessage = function(response) {
console.warn('Received: ' + response.data.join(" "));
};
// Send messages to the worker.
worker.postMessage("**My Message**");
worker.postMessage(33.33);
worker.postMessage(false);
worker.postMessage(null);
worker.postMessage(undefined);
worker.postMessage(6666666n);
worker.postMessage(/^abc$/gim);
worker.postMessage(new Date());
worker.postMessage(new Map());
/* invalid types */
try {
worker.postMessage(/* should error re argument 0 */);
} catch (e) {
console.error(e, '(empty)');
// TypeError: Worker.postMessage: 0 is not a valid argument count for any overload. (empty)
}
try {
worker.postMessage(Symbol("42abc"));
} catch (e) {
console.error(e, '(symbol)');
// DOMException: Worker.postMessage: unsupported type for structured data (symbol)
}
try {
worker.postMessage(document.createElement("form"));
} catch (e) {
console.error(e, '(form)');
// DOMException: Worker.postMessage: unsupported type for structured data (form)
}
try {
worker.postMessage(worker);
} catch (e) {
console.error(e, '(worker)');
// DOMException: The object could not be cloned. (worker)
}
// 1. All the error messages appear first. Which almost makes sense as they prevent
// messages being sent.
// 2. All other messages that return to the UI thread appear after that.
// 3. If you terminate here (in the sequence of postMessage() calls), *none* of the
// other messages is processed. This is a surprise.
// ...rest of our messages...
// Received: Worker says: type of **My Message** is string // Received: Worker says: type of 33.33 is number
// Received: Worker says: type of false is boolean
// Received: Worker says: type of is object
// Received: Worker says: type of is undefined
// Received: Worker says: type of 6666666 is BigInt
// Received: Worker says: type of /^abc$/gim is object
// Received: Worker says: type of Tue Jun 07 2022 08:55:49 GMT-0700 (Pacific Daylight Time) is object
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment