【问题标题】:Why does postMessage called upon terminated worker not throw some error?为什么 postMessage 调用终止的工作人员不会抛出一些错误?
【发布时间】:2017-05-24 01:49:58
【问题描述】:

一个web worker终止后,为什么我调用postMessage不报错?

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

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 在尝试对终止的实例执行操作时会立即抛出异常。

【问题讨论】:

    标签: javascript web-worker


    【解决方案1】:

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

    当worker以close终止自己时,这将向主窗口发送消息。

    你可以这样使用它:

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

    重启worker

    在重新启动工作器时:从技术上讲,如果不自己将其保存在某个位置,就不可能从以前的状态开始。我提出了我在上面实施的这个解决方案:

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

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

    【讨论】:

    • tychus 赢得胜利
    【解决方案2】:

    根据文档,worker的terminate方法

    立即终止 Worker。这并没有为工人提供完成其操作的机会;它只是立即停止。

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

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

    【讨论】:

      猜你喜欢
      • 2021-10-03
      • 2014-08-11
      • 1970-01-01
      • 2021-10-28
      • 2020-03-05
      • 2020-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多