multee-browser
multee-browser
is a "battery" API. It turns the browser's multitasking Web Workers into simple async functions. It works with Typescript. The multee package provided a lot of the inspiration for this work.
Getting started
npm i multee-browser
Why multee-browser helps
Without multee-browser
, you need to listen to messages from your threads, and it is hard to integrate the listener to other part of your code. Also, when there are multiple operations inside the worker, we have to implement the dispatching logic inside the message listener.
The code will look like below without multee-browser
:
// worker.js
self.addEventListener('message', async msg => {
// do heavy load job
let result = 0;
for (let i = 0; i < 100000000; i++) {
result += heavy_and_return_same(i);
}
self.postmessage(result);
});
// main.js
const child = new Worker('./worker');
worker.addEventListener('message', msg => {
// if is job result
part2(msg.data);
});
function part1() {
child.postmessage(payload_for_worker);
}
function part2(result) {
// do the rest with result
}
And with multee-browser
, it's just as easy as calling an async function.
// worker.js
import Multee from 'multee-browser';
const multee = Multee();
const jobA = multee.createHandler('jobA', () => {
// do the heavy load here
let result = 0;
for (let i = 0; i < 100; i++) {
result += heavy_and_return_same(i);
}
return result;
})
export default function {
start: () => {
const worker = multee.start('./worker.js');
return {
run: jobA(worker),
worker: worker
};
}
}
// main.js
import worker from'./worker.js';
async function partA() {
const test = worker.start();
const result = await test.run();
// do the rest with result
console.log(result);
// { result: 4950 }
test.worker.terminate();
}
Browser-specific caveats
-
The browser doesn't have the
require('module')
function. Therefore, the ESM module and import is the more supported option. This is especially true for Web Workers. -
Usually, the file cannot reliably and automatically find out its own name due to browser bundling.
-
The imports need to be accessible from the client through the page loading mechanism. Webpack and esbuild might be able to allow for such bundling and deployments...somehow. The easiest is to bundle the worker files separately using the following:
- Setup:
npm i --save-dev browserify esmify
- Bundle inside
package.json
:
"scripts": {
...
"deploy": "browserify src/worker.js -p esmify > public/worker.js",
...
}
It is possible to apply the same technique a whole folder of workers that deploy into a set of worker bundles.