我可以在网络工作者中存储本地状态吗



我正在使用VSCode学习javascript中的Web Workers。我的工作人员在其onmessage事件期间设置了一个间隔。理想情况下,调用start只会在尚未运行的情况下创建间隔。

onmessage = (event: MessageEvent) => {
let interval;
switch (event.data.command){
case "start":
if (!interval){
interval = setInterval(myFunction, 1000);
}
break;
case "stop":
if (interval){
clearInterval(interval);
interval = null;
}
break;
}
}

问题是interval是在函数的执行过程中定义的,所以我可以在不知道彼此的情况下启动多个间隔。

const worker = new Worker("myworker.ts");
worker.postmessage({command: "start"});
worker.postmessage({command: "start"});
worker.postmessage({command: "start"});

如果我修改web工作程序代码以使用全局变量,就像这样,那么根据VSCode,其他工作程序文件将可以访问间隔变量:

let interval; // Error: `interval` is already defined in `anotherWorker.ts`
onmessage = () => {
// ...
if (!interval){
interval = setInterval(myFunction, 1000);
}
// ...
if (interval){
clearInterval(interval);
interval = null;
}
}

即使每个工作者都有自己的作用域,如果我在工作者之间重用变量名,VSCode也会继续抛出错误。

如何为工作者onmessage函数创建本地状态?

您可以将onmessage处理程序包装在自己的块中,并在那里声明interval。这样,其他模块就看不到它,但它仍然会在不同的消息事件中持续存在。

{ // <- defines a new block
let interval; // <- only for us, but still the same for all message events
onmessage = () => {
// ...
if (!interval){
interval = setInterval(myFunction, 1000);
}
// ...
if (interval){
clearInterval(interval);
interval = null;
}
};
}

我最近在服务工作者中使用@Kaiido的答案这样的方法时遇到了问题。浏览器可能会在合适的时候重新启动服务工作人员(可能还有其他工作人员?(,因此您可能会丢失存储在工作人员中的变量中的状态。

在我的案例中,我创建了一个服务工作者,以便在用户处于非活动状态时将应用程序的所有实例返回到登录页面。这有时会因为浏览器重新启动工作程序并丢失我设置的超时而失败。

如果您希望在服务工作者重新启动时保持状态,则应将状态存储在IndexedDB中,并在重新激活任何工作者本地化状态时重新初始化该状态。

对于需要工作人员保持活动状态的超时和间隔,您可能会强烈考虑在合理的情况下将该功能转移到客户端应用程序中。否则,您可能会考虑以您所能容忍的最大粒度定期发送保活消息,以确保它在该时间间隔内重新激活,并有机会对本应在其睡眠时触发的超时(通过存储在IndexedDB中的时间戳(采取行动。

最新更新