Created
June 7, 2022 15:58
-
-
Save dfkaye/8757576315b1e00252b682dc785d584b to your computer and use it in GitHub Desktop.
Misconceptions about structured clone data and terminating workers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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