网络工作者被终止后,为什么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在尝试对已终止的实例执行操作时立即抛出。
答案 0 :(得分:0)
根据文档,工作人员的terminate方法
立即终止工人。这并不能为工人提供完成业务的机会;它只是立即停止。
我认为既然实例它仍然存在,即使它处于这种死态,执行postMessage
也不会抛出,但由于你的工人没有处理任何操作,它什么都不做。
我无法恢复工作人员,但如果您希望能够随意恢复工作,则可以通过消息设置布尔暂停处理。
答案 1 :(得分:0)
我无法回答为什么,因为我不是那个写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();
您也可以通过这种方式克隆工作人员,因为它不会阻止原始工作人员。