JS Multi-Process
WebWorker
It has brothers of ServicesWorker, AudioWorker, Chrome Workers …
API that allows Web application authors to spawn background workers running scripts in parallel to their main page. This allows for thread-like operation with message-passing as the coordination mechanism. The advantage of this is that laborious processing can be performed in a separate thread, allowing the main (usually the UI) thread to run without being blocked/slowed down.
A worker is an object created using a
constructor (e.g. Worker()
) that runs a named JavaScript file — this file contains the code that will run in the worker thread; workers run in another global context that is different from the current window
. This context is represented by a DedicatedWorkerGlobalScope
object in the case of dedicated workers (standard workers that are utilized by a single script; shared workers use SharedWorkerGlobalScope
).
you can use a large number of items available under window
, including WebSockets, and data storage mechanisms like IndexedDB and the Firefox OS-only Data Store API. See Functions and classes available to workers for more details.
Due to their multi-threaded behavior, web workers only has access to a subset of JavaScript’s features:
- The
navigator
object - The
location
object (read-only) XMLHttpRequest
setTimeout()/clearTimeout()
andsetInterval()/clearInterval()
- The Application Cache
- Importing external scripts using the
importScripts()
method - Spawning other web workers
Workers do NOT have access to:
- The DOM (it’s not thread-safe)
- The
window
object - The
document
object - The
parent
object
Data Transfer
Messages passed between the main page and workers are copied, not shared. Most browsers implement the structured cloning algorithm, which allows you to pass more complex types in/out of Workers such as File
, Blob
, ArrayBuffer
, and JSON objects. However, when passing these types of data usingpostMessage()
, a copy is still made.
Structured cloning is great, but a copy can take hundreds of milliseconds. To combat the perf hit, you can use Transferable Objects.
With Transferable Objects, data is transferred from one context to another. It is zero-copy, which vastly improves the performance of sending data to a Worker. Think of it as pass-by-reference if you’re from the C/C++ world. However, unlike pass-by-reference, the ‘version’ from the calling context is no longer available once transferred to the new context. For example, when transferring an ArrayBuffer from your main app to Worker, the original ArrayBuffer
is cleared and no longer usable. Its contents are (quiet literally) transferred to the Worker context.
worker.postMessage({data: int8View, moreData: anotherBuffer},
[int8View.buffer, anotherBuffer]);
Load External Scripts in Worker
importScripts('utils.js', 'store.js');
And you can also use inline worker
var blob = new Blob([
"onmessage = function(e) { postMessage('msg from worker'); }"
]);
// Obtain a blob URL reference to our worker 'file'.
var blobURL = window.URL.createObjectURL(blob);
var worker = new Worker(blobURL);
Sub-workers
Workers have the ability to spawn child workers. This is great for further breaking up large tasks at runtime. However, subworkers come with a few caveats:
- Subworkers must be hosted within the same origin as the parent page.
- URIs within subworkers are resolved relative to their parent worker’s location (as opposed to the main page).
Keep in mind most browsers spawn separate processes for each worker. Before you go spawning a worker farm, be cautious about hogging too many of the user’s system resources. One reason for this is that messages passed between main pages and workers are copied, not shared. See Communicating with a Worker via Message Passing.
For an sample of how to spawn a subworker, see the example in the specification.
Conditions to use Workers
- Chunk of huge amount of mathematic calculations.
- Separated network requests or blocked I/O.
- Prefetching and/or caching data for later use.
- Code syntax highlighting or other real-time text formatting.
- Spell checker.
- Analyzing video or audio data.
- Background I/O or polling of web services.
- Processing large arrays or humungous JSON responses.
- Image filtering in
- Updating many rows of a local web database.
API
main.js
let errorAlert = false;
(function(window, document) {
if (!window.Worker) return;
const worker = new Worker('worker.js');
// start the worker
worker.postMessage({ type: 'Greet', msg: 'hello, world!' });
// report the error one
worker.postMessage({ type: 'Error', msg: 'cause trouble now!' });
// this worker won't work because the worker is closed
worker.postMessage({ type: 'Close', msg: 'close the worker' });
worker.addEventListener('message', (e) => {
console.log('Worker said: ', e.data);
}, false);
worker.addEventListener('error', (e) => {
console.log('Worker error:', e);
})
setTimeout(() => {
// terminate a worker
if (errorAlert) worker.terminate();
}, 1000);
})(window, document);
worker.js
// the other local scripts
importScripts('utils.js', 'store.js');
console.log('we import function sort and cache', sort, setCache);
self.addEventListener('message', function (e) {
console.log('worker receive message type:' + e.data.type);
switch (e.data.type) {
case 'Greet':
self.postMessage('I receive message: ' + e.data.msg);
break;
case 'Close':
self.postMessage('Close the worker wit message: ' + e.data.msg);
close();
case 'Error':
self.postMessage('2'.toPublic());
default:
break;
}
}, false);
Node.js MultiProcess
see Node.md
doc.
Ref
Worker
- W3C WebWorkers as a standard API declaration. 知其然,知其所以然,打破砂锅问到底。
- MDN WebWorker API standard JavaScript API. 完全掌握用法之道。
- MDN WebWorker UserGuide
- How JavaScript Works: The worker and 5+ used Scenes