Synchronously Wait for Message in Web-Worker

javascript, web-worker

Solution

This is an issue that I also ran into while working with Pyodide. I wanted to 'synchronously' call a function from the main thread.

One solution involves the `Atomic`s and `SharedArrayBuffer` APIs. From the perspective of the web worker, this looks like the following

- `postMessage` the main thread

- freeze ourselves with `Atomics.wait`

- get unfrozen by the main thread

- read the result from a `SharedArrayBuffer`. We can't receive the result as a `postMessage`, because there isn't a synchronous way of asking "did I get a message".

Of course this requires a fair amount of extra code to handle all the serialization, data passing and more.

The main limitation is that to use those APIs, one needs to have the COOP/COEP headers set. The other bit to keep in mind is that this only works on recent browsers such as Safari 15.2 (released in December 2021).

There is also an alternative solution with synchronous XHR and a service worker, but I haven't investigated that option.

Problem

Is there some way to synchronously wait for or check for a new message in a web-worker? I have a large complicated body of code (compiled LLVM from emscripten) that I cannot refactor around callbacks. I need to make sure that code after a certain line doesn't execute until I receive and handle a message from the UI-thread. If I block with a while-loop, the event-loop never runs so I can't receive messages.

Original source