Skip to content

adamziel/js-synchronous-messaging

Repository files navigation

Synchronous messaging in JavaScript

This repository contains a few examples of exchanging messages between JavaScript workers in a blocking / synchronous way.

Node.js

receiveMessageOnPort

This technique uses two mechanisms:

  • Atomics.wait to synchronously wait for the worker to do the work and send the data. This relies on a SharedArrayBuffer, but could potentially work with just Atomics.pause() and no shared buffers.
  • receiveMessageOnPort to synchronously read the data sent by the worker.

Run the code with:

$ node --disable-warning=ExperimentalWarning --experimental-transform-types ./node-receiveMessageOnPort-simple/parent.ts
[child] calling blockingRpc to parent
[parent] onmessage [ 9, 3, 7 ]
[parent] got result [ 3, 7, 9 ]
[child] got result { message: [ 3, 7, 9 ] }

Comlink + receiveMessageOnPort

This extends the Comlink library with a exposeSync/wrapSync API that enables synchronous method calls to another worker. It benefits from all the Comlink goodness, such as transfer handles, propagating errors, etc.

Run the code with:

$ node --disable-warning=ExperimentalWarning --experimental-
transform-types ./node-receiveMessageOnPort-comlink/parent.ts
[parent] started
[parent] Worker stdout: a

[parent] wrapSync() called
[comlink-sync] canHandle() called { obj: 2 }
[comlink-sync] canHandle() called { obj: 3 }
[parent] add() called { sum: 5 }
[comlink-sync] canHandle() called { obj: 2 }
[comlink-sync] canHandle() called { obj: 3 }
[parent] add() called { sum2: 5 }
[comlink-sync] canHandle() called { obj: 'https://wp.org' }

Browsers

Lacking receiveMessageOnPort and easy access to SharedArrayBuffer in web browsers, I looked for another technique. Unfortunately, I'm yet to find one that works.

Motivation

During the development of the PHP-WASM project, integrating asynchronous calls with the synchronous PHP code was a big challenge. In JSPI-enabled runtimes, it all just worked. However, in Asyncify-only runtimes, such as Safari of Node.js < 23, we've spent hundreds of hours tweaking the compilation flags to make it work – just see all these discussions.

The final straw was fcntl() integration. Despite a ton of effort, nothing seemed to work. I finally gave up and decided to just ditch Asyncify and rely on synchronous calls instead.

This is how this repository came to life.

License

GPLv2

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published