async-thread-worker
v0.9.4
Published
async/await abstraction for Web Workers
Readme
About
async-thread-worker presents an abstraction of Web Worker thread communication based on the client-server model. Supported features are:
awaiting thread operations,- integration of basic Web Worker APIs (e.g. transferables, the
terminate()method etc.), and - class methods/interfaces for implementing client-server style functionality.
After introducing some basic examples for quickly getting started, we demonstrate applications using Wasm binaries (C code compiled by Emscripten and Rust code by wasm-pack) embedded inside worker threads.
For other libraries that realize similar functionality, you might also consider:
Getting Started
Installation
$ npm install async-thread-workerUsage
Here's a basic example of implementing a worker (abstracted as thread) and interacting with it.
Use sendRequest() and sendResponse() for client-server style communications.
[ demo | source ]
index.html: Synchronously sending requests to a worker.
// <script src='async-thread-worker.min.js'></script>
const thread = new AsyncThreadWorker.Thread('my-thread-worker.js');
for (let payload of ['a', 'b', 'c', 'd']) {
const response = await thread.sendRequest(payload);
console.log('[main] got response:', response);
}my-thread-worker.js: Implementation of the worker. Use the provided id to respond to a request.
importScripts('async-thread-worker.min.js');
class MyThreadWorker extends AsyncThreadWorker.ThreadWorker {
onRequest(id, payload) { // impl
console.log('[worker] got request with:', payload);
this.sendResponse(id, payload.toUpperCase());
}
}
const myThreadWorker = new MyThreadWorker(self);The results in the developer console:
[worker] got request: a
[main] got response: A
[worker] got request: b
[main] got response: B
[worker] got request: c
[main] got response: C
[worker] got request: d
[main] got response: DExamples
- simple - Basic client-server communications with a worker. [ live | source | howto ]
- tasks - Delegating various tasks to a worker (calculator). This example also demonstrates error handling with
try/catchand thesendError()API. [ live | source ] - serial-vs-parallel - Running multiple workers serially/parallelly. [ live | source ]
- terminate -
terminate()api example. [ live | source ] - transferables - Transfering an
ArrayBufferobject back and forth for efficient drawing. ThesendRequest()andsendResponse()APIs support transferable objects. [ live | source ] - class-sharing - Passing a JavaScript class to a worker. [ live | source ]
- wasm-ffmpeg - webm/mp4 encoder app inspired by "Running FFMPEG with WASM in a Web Worker". In this app, we use
async-thread-workerinstead of Comlink in order to control encoder threads in more client-server oriented style. [ live | source ]
- rust-fern-bench - WebVR app for benchmarking fractal computation with Rust+wasm vs JavaScript. [ live | source ] 🔗
API
AsyncThreadWorker.Thread
The Thread class is for abstraction of the main thread's side (client).
constructor(path)Creates aThreadobject that is a worker's interface. The underlying Web Worker object wrapped byThreadis also created based on its implementation specified bypath.pathstring The path to a worker's implementation.
sendRequest(payload=undefined, transferables=[])Sends a request to the worker (server) with datapayload. Transferable objects can be specified in the optionaltransferblesarray so that they are efficiently sent to the other thread without structured clone. Returns a promise corresponding to the server's action (sendResponse()orsendError()).payloadobject | primitive e.g.42, or{name: 'foo', input: buf}, wherebufis anArrayBuffer.transferablesArray<object> e.g.[buf,]
getWorker()Returns the raw Web Worker object wrapped byThread(ornullif the worker is already terminated).terminate()Immediately terminates the worker (internally usingWorker.terminate()).
AsyncThreadWorker.ThreadWorker
The ThreadWorker class is for abstraction of the worker's side (server).
constructor(self, opts={})Creates aThreadWorkerobject that represents the worker thread by wrapping the bare Web Worker object (self).selfDedicatedWorkerGlobalScope The Web Worker object to be wrapped.optsobject Optional data that can be passed toonCreate(opts).
onRequest(id, payload)Called when the worker thread (server) received a request with datapayloadfrom the main thread (client). Implement this method to respond to the client by eithersendResponse()orsendError().idstring An auto-generated request id to be required bysendResponse()orsendError().payloadobject | primitive
sendResponse(id, payload=undefined, transferables=[])Sends a response to the main thread (client) with datapayload. Transferable objects can be specified in the optionaltransferblesarray so that they are efficiently sent to the other thread without structured clone.idstring A request id provided byonRequest().payloadobject | primitive e.g.42, or{name: 'foo', output: buf}, wherebufis anArrayBuffer.transferablesArray<object> e.g.[buf,]
sendError(id, error)Sends an error response to the main thread (client) with dataerror.idstring A request id provided byonRequest().errorobject | primitive
onCreate(opts)Called when theThreadWorkeris created. One may override this method when extending theThreadWorkerclass.optsobject Optional parameters given toconstructor().
Build
$ npm install # set up build tools
$ npm run build