如何让网络工作者同时执行多项任务? [英] How to let a webworker do multiple tasks simultaneously?

查看:32
本文介绍了如何让网络工作者同时执行多项任务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图让 Web-Worker 管理其状态,同时为多个异步请求提供服务.

worker.ts 文件

let a =0;//这是我工人的状态让 worker=self 与 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)}}

这是我的主文件:main.ts

let w =new Worker("./worker.ts", {type: "module"})让 wf =async (op: string)=>{w.postMessage(op);return new Promise((res,rej)=>{w.onmessage=res;});}(异步()=>{让 f1 = 等待 wf("+1");console.log("f1",f1.data);})();(异步()=>{让 f2 = 等待 wf("+2");console.log("f2",f2.data);})()

只返回f2f1丢失.我使用超时来模拟说一些由工人自己完成的异步任务.

我如何同时接收f1f2?

解决方案

您的问题是您正在尝试采用基于事件的 API 并将其用作基于 Promise 的 API,但是事件可能会触发多次,而 Promise 应该可以解决只有一次.

Worker 和主线程之间的通信是通过发送和接收消息来工作的,但是这些消息之间默认没有一对一的关系.通信的两端(端口)将简单地堆叠传入的消息,并在有时间时按顺序处理它们.

在您的代码中,f1 的主线程的 worker.onmessage 处理程序已被第二次调用 f2 同步覆盖(稍后一个微任务,但这对我们来说仍然是同步的).
您可以使用 addEventListener 方法附加您的事件,至少这样它就不会被覆盖.但即便如此,当第一个 message 事件将在 worker 上触发时,两个处理程序都会认为它确实到达了自己的消息,而实际上它是 f2.所以这不是您所需要的...

您需要的是建立一个通信协议,允许两端识别每个任务.例如,您可以使用包含 .UIID 成员的对象包装所有任务的数据,确保两端以这种方式包装它们的消息,然后从主线程检查该 UUID 以解析适当的 Promise.

但这在实现和使用上可能会变得有点复杂.


我个人最喜欢的方式是创建一个新的MessageChannel 每个任务.如果你不知道这个 API,我邀请你阅读我的这个答案解释基础.

因为我们确定唯一一条消息会通过这个 MessageChannel 是 Worker 对我们发送给它的一个任务的响应,所以我们可以像 Promise 一样等待它.>

我们要做的就是确保在 Worker 线程中我们通过传输的端口而不是全局范围进行响应.

const url = getWorkerURL();const 工人 = 新工人(网址)const workerFunc = (op) =>{//我们创建一个新的 MessageChannelconst channel = new MessageChannel();//我们将其端口之一传输到 Worker 线程worker.postMessage(op, [channel.port1]);返回新的承诺((res,rej)=> {//我们从 MessageChannel 的剩余端口监听消息channel.port2.onmessage = (evt) =>res(evt.data);});}(异步() => {const f1 = await workerFunc("+1");console.log("f1", f1);})();(异步() => {const f2 = await workerFunc("+2");console.log("f2", f2);})()//所以只有函数 getWorkerURL() {const elem = document.querySelector( '[type="worker-script"]' );const script = elem.textContent;const blob = new Blob( [script], { type: "text/javascript" } );返回 URL.createObjectURL( blob );}





        
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆