Search code examples
javascriptweb-worker

Is there some kind of load event for web-workers?


I faced some problem when tried to use broadcast channel to communicate between main script and workers. I have code below in main script:

const channel = new BroadcastChannel('my_bus');
const worker = new Worker('worker.js');
const secondWorker = new Worker('second-worker.js');

channel.postMessage('1000');

and the similar code in both workers:

const bc = new BroadcastChannel('my_bus');

bc.onmessage = () => {
  console.log('worker get length');
}

The problem is when the message emitted from main script, workers are not loaded yet, so they skip the message. I am sure about it, because if I do something like this, it works fine:

setTimeout(() => {
  channel.postMessage('1000');
}, 100)

Is there some way to trigger callback after worker script has been loaded?


Solution

  • As per last comment, I'll wrote my suggestion as answer:

    You can make the worker emit a message when they're loaded, and you listen to that message on main script. That usually what we do with web workers: they emit a message to the main thread to say "I'm ready to receive stuff".

    A possible implementation could be:

    // assumes the first `message` from workers is always the "loaded" ones
    const loaded = w =>
      new Promise(r => w.addEventListener("message", r, { once: true }));
    
    // Code runs inside async function, so we can use `await`
    async function main() {
      const channel = new BroadcastChannel("my_bus");
      const worker = new Worker("worker.js");
      const secondWorker = new Worker("second-worker.js");
    
      await Promise.all([
        loaded(worker), 
        loaded(secondWorker)
      ]);
    
      // this will be post only once all the workers have been loaded
      channel.postMessage("1000");
    }
    
    // call the main function
    main();
    

    The workers' code will looks like:

    const bc = new BroadcastChannel("my_bus");
    
    bc.onmessage = () => {
      console.log("worker get length");
    };
    
    postMessage("loaded");