虽然我理解JavaScript本质上是单线程的,并且通常对这些事情不满意,但我想知道是否有任何方法可以让WebWorker等到主线程提供一些数据而不破坏WebWorker的调用堆栈.
由于这是一个有趣的项目,我可以使用新技术和不能在旧浏览器上可靠运行的东西,我不介意深奥的黑客,只要它们工作.
我考虑过的其他一些解决方案:
在循环中连续轮询LocalStorage,直到预定密钥上有数据.这似乎是有效的,因为即使在循环中轮询时,其他线程的LocalStorage更新应该对当前线程可见,从所有关于LocalStorage的线程安全性的讨论判断并且有多个选项卡写入相同的LocalStorage键.这种方法的缺点是它不是真正"等待",即工作线程仍然消耗在LocalStorage上的全部CPU使用率.虽然LocalStorage通常使用锁实现,但是长时间不能持有LocalStorage锁(锁被释放一次getItem或setItem返回).
ECMAScript 6 yield.这在这里不起作用,因为它需要调用堆栈中的所有函数(直到你想要屈服的地方)被标记为生成器函数.我想暂停我的WebWorker的地方有一个包含WebAssembly函数的调用堆栈,它不能标记为生成器函数.
IndexedDB的.这不起作用,因为IndexedDB不支持同步请求.
我知道这个类似的问题,但是这个问题专门讨论了这个onmessage事件,并在2012年之前被问到,yield并且引入了WebAssembly.
有没有办法以某种方式模拟WebWorker线程上的锁,否则,它会等到某些数据可用?
我试图让 Web Worker 管理其状态,同时服务多个异步请求。
工人.ts 文件
let a =0; //this is my worker's state
let worker=self as unknown as Worker;
worker.onmessage =(e)=>{
console.log("Rec msg", e.data);
if(e.data === "+1"){
setTimeout(()=>{
a=a+1;
worker.postMessage(a);
},3000);
}else if(e.data=== "+2"){
setTimeout(()=>{
a=a+2;
worker.postMessage(a);
},1000)
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的主文件:main.ts
let w =new Worker("./worker.ts", {type: "module"})
let wf =async (op: string)=>{
w.postMessage(op);
return new Promise<any>((res,rej)=>{
w.onmessage=res;
});
}
(async()=>{
let f1 = await wf("+1");
console.log("f1",f1.data);
})();
(async()=>{
let f2 = await wf("+2");
console.log("f2",f2.data);
})()
Run Code Online (Sandbox Code Playgroud)
只能f2归还,就f1 …
javascript ×2
web-worker ×2
deno ×1
locking ×1
node.js ×1
synchronous ×1
typescript ×1
webassembly ×1