An async/await
abstraction for Web Workers
async-thread-worker
presents an abstraction of Web Worker thread communication based on the client-server model. Supported features are:
await
ing 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:
$ npm install async-thread-worker
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: D
- 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/catch
and thesendError()
API. [ live | source ] - serial-vs-parallel - Running multiple workers serially/parallelly. [ live | source ]
- terminate -
terminate()
api example. [ live | source ] - transferables - Transfering an
ArrayBuffer
object 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-worker
instead 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 ] 🔗
The Thread
class is for abstraction of the main thread's side (client).
-
constructor(path)
Creates aThread
object that is a worker's interface. The underlying Web Worker object wrapped byThread
is also created based on its implementation specified bypath
.path
string 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 optionaltransferbles
array so that they are efficiently sent to the other thread without structured clone. Returns a promise corresponding to the server's action (sendResponse()
orsendError()
).payload
object | primitive e.g.42
, or{name: 'foo', input: buf}
, wherebuf
is anArrayBuffer
.transferables
Array<object> e.g.[buf,]
-
getWorker()
Returns the raw Web Worker object wrapped byThread
(ornull
if the worker is already terminated). -
terminate()
Immediately terminates the worker (internally usingWorker.terminate()
).
The ThreadWorker
class is for abstraction of the worker's side (server).
-
constructor(self, opts={})
Creates aThreadWorker
object that represents the worker thread by wrapping the bare Web Worker object (self
).self
DedicatedWorkerGlobalScope The Web Worker object to be wrapped.opts
object Optional data that can be passed toonCreate(opts)
.
-
onRequest(id, payload)
Called when the worker thread (server) received a request with datapayload
from the main thread (client). Implement this method to respond to the client by eithersendResponse()
orsendError()
.id
string An auto-generated request id to be required bysendResponse()
orsendError()
.payload
object | primitive
-
sendResponse(id, payload=undefined, transferables=[])
Sends a response to the main thread (client) with datapayload
. Transferable objects can be specified in the optionaltransferbles
array so that they are efficiently sent to the other thread without structured clone.id
string A request id provided byonRequest()
.payload
object | primitive e.g.42
, or{name: 'foo', output: buf}
, wherebuf
is anArrayBuffer
.transferables
Array<object> e.g.[buf,]
-
sendError(id, error)
Sends an error response to the main thread (client) with dataerror
.id
string A request id provided byonRequest()
.error
object | primitive
-
onCreate(opts)
Called when theThreadWorker
is created. One may override this method when extending theThreadWorker
class.opts
object Optional parameters given toconstructor()
.
$ npm install # set up build tools
$ npm run build