Search code examples
javascriptweb-worker

Is there a way to have different worker functions in one file


Reading about web workers I stumbled across this example from mdn. The worker.js is just once simple function. So when we post a message to the worker the onmessage part is then started by the worker. In the simple example the worker just multiplies two numbers. But what if I want a worker that can also add, divide etc? Do I need to create a new worker file (e.g. worker_add.js) for each function I want my worker to run? Or what is the cleaner way to deal with this?

I was thinking of having a string posted as first argument to the worker

myWorker.postMessage(["method", arg1, arg2]);

and then in my worker I have if/else conditionals which check if the string matches and then execute different code.

importScripts('emscripten.js')

onmessage = function(e) {
    console.log('Message received from main script.');
    if (e.data[0] == "method1")
    {
        Module.method1(e.data[1].byteOffset, e.data[2]);
        postMessage(e.data[1]);        
    }

    else if (e.data[0] == "method2")
    {
        var ret= Module.method2();
        postMessage(ret);
    }

    console.log('Posting message back to main script');
}

Solution

  • In the spirit of Emil's answer I found an example on html5rocks. I feel like this is slightly cleaner than Emil's answer.

    The main script looks like this

    <button onclick="sayHI()">Say HI</button>
    <button onclick="unknownCmd()">Send unknown command</button>
    <button onclick="stop()">Stop worker</button>
    <output id="result"></output>
    
    <script>
      function sayHI() {
        worker.postMessage({'cmd': 'start', 'msg': 'Hi'});
      }
    
      function stop() {
        // worker.terminate() from this script would also stop the worker.
        worker.postMessage({'cmd': 'stop', 'msg': 'Bye'});
      }
    
      function unknownCmd() {
        worker.postMessage({'cmd': 'foobard', 'msg': '???'});
      }
    
      var worker = new Worker('doWork2.js');
    
      worker.addEventListener('message', function(e) {
        document.getElementById('result').textContent = e.data;
      }, false);
    </script>
    

    and the worker doWork2.js like this:

    self.addEventListener('message', function(e) {
      var data = e.data;
      switch (data.cmd) {
        case 'start':
          self.postMessage('WORKER STARTED: ' + data.msg);
          break;
        case 'stop':
          self.postMessage('WORKER STOPPED: ' + data.msg +
                           '. (buttons will no longer work)');
          self.close(); // Terminates the worker.
          break;
        default:
          self.postMessage('Unknown command: ' + data.msg);
      };
    }, false);