为什么postMessage调用终止的worker不会抛出一些错误?

时间:2017-05-21 00:24:05

标签: javascript web-worker

网络工作者被终止后,为什么postMessage在我打电话时不会抛出错误?

是否可以在没有构造函数new Worker("same-worker.js")的情况下重新启动具有现有已终止实例的worker?

const myWorker = new Worker("my-worker.js");
myWorker.addEventListener("message", function(event) {
    const message = event.data;
    console.log("from worker", message);
    myWorker.terminate();
    myWorker.postMessage("");
    // what happens here, is only silence
    // Why not throw error?
});
myWorker.postMessage(""); //start it, maybe receive a response

编辑:我问的是这个特定设计的基本原理。 XHR,WebSocket和WebRTC在尝试对已终止的实例执行操作时立即抛出。

2 个答案:

答案 0 :(得分:0)

根据文档,工作人员的terminate方法

  

立即终止工人。这并不能为工人提供完成业务的机会;它只是立即停止。

我认为既然实例它仍然存在,即使它处于这种死态,执行postMessage也不会抛出,但由于你的工人没有处理任何操作,它什么都不做。

我无法恢复工作人员,但如果您希望能够随意恢复工作,则可以通过消息设置布尔暂停处理。

答案 1 :(得分:0)

tl;dr jsFiddle

我无法回答为什么,因为我不是那个写javascript标准的人。但是没有任何迹象表明工人是否已经终止。

检测终止

如果您需要检测此状态,则必须创建自己的API。我提出这个简单的基于功能的草案作为起点:

//Override worker methods to detect termination
function makeWorkerSmart(workerURL) {
    // make normal worker
    var worker = new Worker(workerURL);
    // assume that it's running from the start
    worker.terminated = false;
    // allows the worker to terminate itself
    worker.addEventListener("message", function(e) {
      if(e.data == "SECRET_WORKER_TERMINATE_MESSAGE") {
          this.terminated = true;
          console.info("Worker killed itself.");
      }
    });
    // Throws error if terminated is true
    worker.postMessage = function() {
        if(this.terminated)
            throw new Error("Tried to use postMessage on worker that is terminated.");
        // normal post message
        return Worker.prototype.postMessage.apply(this, arguments);
    }
    // sets terminate to true
    // throws error if called multiple times
    worker.terminate = function() {
        if(this.terminated)
            throw new Error("Tried to terminate terminated worker.");
        this.terminated = true;
        // normal terminate
        return Worker.prototype.terminate.apply(this, arguments);
    }
    // creates NEW WORKER with the same URL as itself
    worker.restart = function() {
        return makeWorkerSmart(workerURL);
    }
    return worker;
}

要检测工作人员的终止,您需要在每个工作人员中运行此代码:

  function makeInsideWorkerSmart(workerScope) {
      var oldClose = workerScope.close;
      workerScope.close = function() {
          postMessage("SECRET_WORKER_TERMINATE_MESSAGE");
          oldClose();
      }
  }
  makeInsideWorkerSmart(self);

当工作人员以close终止自身时,这将向主窗口发送消息。

你可以像这样使用它:

var worker = makeWorkerSmart(url);
worker.terminate();
worker.postMessage("test"); // throws error!

重新启动工作人员

从重新启动工作人员开始:从技术上讲,从一些以前的状态开始而不将其保存在某个地方是不可能的。我提出了我在上面实现的解决方案:

worker.terminate();
worker = worker.restart();

您也可以通过这种方式克隆工作人员,因为它不会阻止原始工作人员。