multiworker
v1.0.3
Published
Wrapper to make web workers easy.
Downloads
4
Readme
Summary
MultiWorker is a wrapper around node's and the browser's native (web) worker API. Features include:
- Post data to workers and use callbacks to handle results.
- Queue processes across multiple worker threads.
- Build workers from functions, instead of needing a separate JS file.
Installation
Install via NPM:
npm install --save multiworker
Then use in your script:
import MultiWorker from 'multiworker';
Or, include the script the old fashioned way to make the MultiWorker constructor available globally:
<script src="dist/multiworker.min.js"></script>
Usage
Basic usage
A MultiWorker instance is created with a function which is used as the code for the worker.
var worker = new MultiWorker(function () {
self.receive = function (n) {
self.return(n + 1);
}
});
In order to interact with the worker, we use the post method. This triggers the self.receive function inside the worker, which returns a value with self.return.
worker.post(5, function (n) {
console.log(n); // => 6
});
Both worker.post()
in the main thread and self.return()
and self.post()
in the worker can receive an array of transfers as last argument, to support Transferables.
var worker = new MultiWorker(function () {
self.receive = function (inputBuffer) {
// Worker now has ownership of the input buffer
var resultBuffer = inputBuffer
self.return(resultBuffer, [resultBuffer]);
// Ownership of the result buffer has been transferred to the main thread
}
});
var inputBuffer = new ArrayBuffer(5);
worker.post(inputBuffer, function(resultBuffer) {
// Main thread now has ownership of the result buffer
}, [inputBuffer]);
// Ownership of the input buffer has been transferred to the worker
Options
worker
When creating a MultiWorker instance, a function can be passed:
var worker = new MultiWorker(function () {
self.receive = self.return; // Simply return the input
});
Alternatively, a filepath, URL, or a stringified IIFE can be used.
var worker = new MultiWorker('workers/example.js');
worker.post('foo', function () {
// This post won't occur until example.js has been fetched and the worker ready.
});
The worker can also be defined in an options object:
var worker = new MultiWorker({
worker: function () {
self.receive = self.return; // Simply return the input
}
});
The worker url can also be passed as first argument, and all other options in an object literal as second argument:
var worker = new MultiWorker('workers/example.js', { threads: 2 })
callback
A function to be called whenever a worker sends a value back to the main program via self.post or self.return.
var worker = new MultiWorker({
worker: function () {
self.receive = self.return; // Simply return the input
},
callback: function (val) {
console.log(val);
}
});
worker.post(1); // The callback function above will log 1 in the console
If a callback is passed as an argument when the post request is made, then the default callback is not used.
var worker = new MultiWorker({
worker: function () {
self.receive = self.return; // Simply return the input
},
callback: function (val) {
console.log(val);
}
});
worker.post(1, function (val) {
alert(val); // The callback function above will not be used. 1 will be alerted.
});
threads
The number of workers to spawn. The default is 1.
Multiple web workers:
var worker = new MultiWorker({
worker: function () {
self.receive = self.return; // Simply return the input
},
threads: 2
});
// The posts below are processed in parallel.
// There is a chance that the second post will return first.
worker
.post(42)
.post(11);
A single web worker:
var worker = new MultiWorker({
worker: function () {
self.receive = self.return; // Simply return the input
},
threads: 1
});
// The posts below are processed in series.
worker
.post(42)
.post(11);
dependencies
An array of named functions that can be used globally in the workers. These functions must be named and not make references to data outside the function scope.
var worker = new MultiWorker({
worker: function () {
self.receive = function (n1, n2) {
self.return(multiply(n1, n2) + add(n1, n2));
}
},
dependencies: [
function multiply(n1, n2) {
return n1 * n2;
},
function add(n1, n2) {
return n1 + n2;
}
]
});
worker.post(10, 2, function (n) {
console.log(n); // => 32
});
MultiWorker Methods
post([...args], [callback], [transfers])
Interact with a MultiWorker instance. This method accepts an arbitrary number of parameters, which the worker can access with the self.receive method.
A callback can be passed - this is used instead of any default callback that may have been defined when creating the worker instance.
var worker = new MultiWorker(function () {
self.receive = function (n1, n2) {
self.return(n1 + n2);
}
});
worker.post(2, 2, function (result) {
console.log(result); // => 4
});
terminate([callback | instant])
Terminates the MultiWorker instance. The instance can no longer be used once this method has been called.
// Wait for post to return, then terminate
worker.post(10).terminate();
// Wait for post to return, then terminate and run the callback
worker.post(10).terminate(function () {
console.log('Worker terminated');
});
// Terminate instantly, without waiting for result from any pending posts
worker.post(10).terminate(true);
Worker Methods
A few methods are made available inside the workers. These are attached to the self object.
self.receive([...args])
Fired in response to calling post() on a MultiWorker instance. This is the start of any process from within a worker.
var worker = new MultiWorker(function () {
self.receive = function (n1, n2) {
self.return(n1 + n2);
}
});
worker.post(2, 2, function (result) {
console.log(result); // => 4
});
self.return([...args], [transfers])
Sends a response back to the main thread. This will be called inside of self.receive - see the code example for that method for usage.
self.post([...args], [transfers])
Similar to self.return, but will not mark the current task as finished. self.return must be called after all work is done in order to start processing the next item in the queue.
var worker = new MultiWorker({
worker: function () {
self.receive = function () {
var i = 100;
// A pointless loop to demonstrate.
// A real-world usage could be a progress bar.
while (i--) {
if (i) {
self.post(i);
} else {
self.return(i);
}
}
}
},
callback: function (n) {
if (!this.done) {
console.log('left to complete: ' + n);
} else {
console.log('Finished');
}
}
});
worker
.post()
.post(); // This second post won't execute until self.return is called in response to the previous post.
Developing
To continuously run the tests while editing, run
npm start
and open your browser on http://localhost:3000.
To build the standalone version, run
npm run build
To ensure correct code style and that the library runs both in node and browsers, run
npm test
License
This project is licensed under the ISC License - see the LICENSE.md file for details