For more tips like this, sign up to the weekly newsletter!

Propagate errors from web workers

The only way to communcate between a web worker and the page is via postMessage calls. But this way you can only send messages between them, there is no dedicated error channel.

For example, the page calls the worker for some calculations, and the worker responds with the result. But what if there was an error during the processing, on the worker's side?

You can check for an Error object on the receiver side, but that's like using a "magic" value.

A more roboust way is to use an object with an error and a result property, just like how Node-style callbacks work

When the worker is run, pass either a result or an error back:

if (typeof event.data !== "number") {
  event.ports[0].postMessage({error: "Not a number"});
}else {
  event.ports[0].postMessage({result: event.data * 2});
}

On the receiver side, check if there was an error:

channel.port1.onmessage = ({data}) => {
  if (data.error) {
    // Handle error
  }else {
    // Handle result
  }
}

With this construct, promisifying a call to the worker with correct error propagation becomes easy:

const call = (arg) => {
  return new Promise((res, rej) => {
    // Set up channel and call the worker
    
    channel.port1.onmessage = ({data}) => {
      if (data.error) {
        rej(data.error);
      }else {
        res(data.result);
      }
    }
  });
}

await call(10);
Try it
Learn more: