Search code examples
javascriptweb-worker

can I store local state in a web worker


I'm learning Web Workers in javascript, using VSCode. My worker sets up an interval during its onmessage event. Ideally calling start will only ever create the interval if it isn't already running.

onmessage = (event: MessageEvent) => {
  let interval;

  switch (event.data.command){
    case "start":
      if (!interval){
        interval = setInterval(myFunction, 1000);
      }
      break;
    case "stop":
      if (interval){
        clearInterval(interval);
        interval = null;
      }
      break;
  }
}

The problem is that interval becomes defined within the execution of the function, so I could start multiple intervals without any of them knowing about one another.

const worker = new Worker("myworker.ts");
worker.postmessage({command: "start"});
worker.postmessage({command: "start"});
worker.postmessage({command: "start"});

If I modify the web worker code to use a global variable, like this, then according to VSCode other worker files will have access to the interval variable:

let interval; // Error: `interval` is already defined in `anotherWorker.ts`

onmessage = () => {
  // ...
  if (!interval){
    interval = setInterval(myFunction, 1000);
  }

  // ...
  if (interval){
    clearInterval(interval);
    interval = null;
  }
}

Even if each worker gets its own scope, VSCode will continue to throw errors if I reuse variable names across workers.

How can I create a local state for the worker onmessage function?


Solution

  • You can wrap your onmessage handler in its own block, and declare your interval there. This way, other modules won't see it, but it will still persist across different message events.

    { // <- defines a new block
      let interval; // <- only for us, but still the same for all message events
    
      onmessage = () => {
        // ...
        if (!interval){
          interval = setInterval(myFunction, 1000);
        }
    
        // ...
        if (interval){
          clearInterval(interval);
          interval = null;
        }
      };
    }