🌐

Convenient Logging in Web Workers

Interestingly the standard console object doesn’t quite work how you would expect in web workers.

You can do a console.log, but it will appear in it’s own tab in the console of devtools.

See below workaround by using a MessageChannel to send messages to the main thread. We start in our worker, by assigning a MessagePort to which is passed in via an initial message.

// worker.js
/** @type {MessagePort} */
let mport;

self.onmessage = (event) => {
  switch (event.data) {
    case "console":
      mport = event.ports[0];
      break;
  }
};

const log = (...args) => {
  if (mport) {
    mport.postMessage(args);
  } else {
    // the message port is not yet connected
    console.log("worker log", args);
  }
};

Some plumbing is then required when the worker is first created to connect the message port.

// main.js
const mchan = new MessageChannel();

const worker = new Worker(new URL("./worker.js", import.meta.url));
worker.postMessage("console", [mchan.port2]);

mchan.port1.onmessage = (event) => {
  const args = event.data; // Array of args to console.log()
  args.unshift("Worker:"); // Add an arg to identify the worker
  console.log.apply(console, args);
};

And that’s it, we have logging from our worker hitting the main thread’s console.

References

This (now aged) Git repository from 2011 - WorkerConsole is a great example of how to use the console object in a web worker.