有没有办法在一个文件中有不同的工作函数

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

阅读有关 web workers 的文章时,我从 mdn 中偶然发现了这个 exampleworker.js 只是一个简单的函数。 因此,当我们 post 向工作人员发送消息时, onmessage 部分将由工作人员启动。在这个简单的例子中,工作人员只是将两个数字相乘。但是,如果我想要一个可以加、除等的 worker 怎么办?我是否需要为我希望我的工作人员 运行 的每个功能创建一个新的工作人员文件(例如 worker_add.js)?或者更简洁的处理方法是什么?

我正在考虑将字符串 posted 作为工作程序的第一个参数

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

然后在我的 worker 中我有 if/else 条件判断字符串是否匹配然后执行不同的代码。

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');
}

除了在消息本身中传递一些元数据之外,我认为没有更好的方法来做你想做的事情。

但是您的实施可以很容易地改进。而不是切换器,只是始终将第一个参数视为函数名,所有其他参数都是此函数的参数,函数结果直接 post 返回:

onmessage = function(e) {
  postMessage(Module[e.data[0]].apply(Module, e.data.slice(1)));
}

简单的一行,它关心你的 worker 中的任意数量的函数。

如果辅助函数结果是异步的,您可以检查函数结果是否为例如Promise 和 post 承诺的消息 resolve 而不是直接 post 发送消息。

由于您可以通过字符串化 AJAX,您可以轻松地在您的 worker 中实现条件逻辑。

只需传递一个参数来告诉工作人员要做什么:

//This snippet won't run, it's just to illustrate

//main.js
var worker = new Worker('/js/worker.js');

worker.addEventListener("message", function(event) {
  if (event.data["do"] == "main") {
    console.log("One task complete");
  } else if (event.data["do"] == "second") {
    console.log("Other task complete");
  }
}, false);

function doMainTask(taskParam) {
  worker
    .postMessage({
      taskParam: JSON.stringify(taskParam),
      "do": "main"
    });
}

function doSecondTask(taskParam) {
  worker
    .postMessage({
      taskParam: JSON.stringify(taskParam),
      "do": "second"
    });
}

//worker.js

function messageHandler(event) {
  var obj = JSON.parse(event.data);

  var str = "";
  if (obj["do"] == "main") {
    str = main(obj.taskParam);
  } else if (obj["do"] == "second") {
    str = second(obj.taskParam);
  }
  this.postMessage({
    msg: str,
    "do": obj["do"],
    obj: obj
  });
}
this.addEventListener('message', messageHandler, false);

function main(taskParam) {
  return "main";
}
function second(taskParam) {
  return "second";
}

本着 Emil 回答的精神,我在 html5rocks 上找到了一个例子。我觉得这比 Emil 的回答稍微干净一些。

主要脚本如下所示

<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>

和工人 doWork2.js 是这样的:

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);