Initializing web workers

Viewed 1484

It seems the only communication from host to worker is postMessgage and onmessage. If the worker requires some dynamic initialization (as in constructor, here: regular expression to use later), what is the best way to do this?

A possibility would be to let data be an object, and have e.g. an action parameter, and to check this on every run. This seems a bit kludgey.

2 Answers

The communication channel between different agents is very low-level, but you can easily build a higher level communication based on that. I'd use objects to communicate different "events":

  { event: "init", data: [/d/] }

Based on these events, you can create different events to represent e.g. function calls and their response:

 { event: "call-init", data: [/d/] } // >>>
 { event: "return-init", data: ["done"] } // <<<

Then you can build a wrapper around that, that sends and handles the response, something like:

    async function call(name, ...args) {
      channel.send("call-" + name, args);
      return await cannel.once("return-" + name);
   }

   channel.init = call.bind(null, "init");

Then your code turns into something along the lines of:

  const channel = new Channel(worker);
  await channel.init(/d/);
 await channel.doOtherStuff();

That's just to give you the basic idea.

A more ad-hoc approach than Jonas' solution abuses the Worker's name option: You can e.g. pass the regex string in this name and use it later:

test.js

var a = new Worker("worker.js", {name: "hello|world"})

a.onmessage = (x) => {
  console.log("worker sent: ")
  console.log(x)
}
 
a.postMessage("hello")

worker.js

var regex = RegExp(this.name);

onmessage = (a) => {
  if (regex.test(a.data)) {
    postMessage("matches");
  } else {
    postMessage("no match for " + regex);
  }
}
Related