web-worker - 如何让童工与多个工人一起向 Deno 中的父母发送消息?
问题描述
我是工人新手,所以基于这个问题,我尝试了以下操作:
// main.t
for(let idx = 0; idx < 4; idx++){
const worker = new Worker(new URL('./worker.ts', import.meta.url).href, {
type: "module",
deno: { namespace: true},
});
worker.postMessage({ id: idx, name: 'text1', email: 'ea@da.com' });
worker.addEventListener('message', message => {
console.log('response', message.data)
})
}
// worker.ts
self.onmessage = async (params) => {
const data = params.data
console.log('params', data)
data.name = 'text2'
self.postMessage(data)
self.close()
}
期待这个:
params { id: 2, name: "text1", email: "ea@da.com" }
response { id: 2, name: "text2", email: "ea@da.com" }
params { id: 0, name: "text1", email: "ea@da.com" }
response { id: 0, name: "text2", email: "ea@da.com" }
params { id: 1, name: "text1", email: "ea@da.com" }
response { id: 1, name: "text2", email: "ea@da.com" }
params { id: 3, name: "text1", email: "ea@da.com" }
response { id: 3, name: "text2", email: "ea@da.com" }
但相反,我得到的是:
params { id: 0, name: "text1", email: "ea@da.com" }
params { id: 1, name: "text1", email: "ea@da.com" }
params { id: 2, name: "text1", email: "ea@da.com" }
params { id: 3, name: "text1", email: "ea@da.com" }
response { id: 3, name: "text2", email: "ea@da.com" }
有人可以帮我解决我哪里出错了吗?为什么我只得到最后一个工人的回应,而不是得到每个工人的回应?
解决方案
有人可以帮我解决我哪里出错了吗?为什么我只得到最后一个工人的回应,而不是得到每个工人的回应?
我怀疑这是因为您在postMessage
完成之前关闭了每个工人。在你的worker.ts
:
self.postMessage(data)
self.close()
从 MDN 页面DedicatedWorkerGlobalScope.close():
接口的
close()
方法丢弃在's 事件循环中排队的任何任务,有效地关闭了这个特定的范围。DedicatedWorkerGlobalScope
DedicatedWorkerGlobalScope
下面,我对您的示例进行了重构,增加了一些类型安全性和更详细的日志记录,以便您可以查看更多事件和一些时间信息。在示例中,不是self.close()
从每个工作人员内部调用,而是Worker.terminate()
在接收到每条消息后(在我们完成工作人员之后)在主范围的消息事件处理程序中调用。您可以忽略三斜杠指令(尽管它们可能有助于在您的编辑器中进行类型检查)。
util.ts
:
export type ExampleData = {
sender: string;
timestamp: number;
};
export function formatMessage (
direction: 'in' | 'out',
callerName: string,
interlocutorName: string,
timestamp: number,
): string {
// 7 === Math.max('receive'.length, 'post'.length);
const directionString = (direction === 'in' ? 'receive' : 'post').padEnd(7);
// 8 === Math.max('worker n'.length, 'main'.length);
return `${(callerName).padEnd(8)} ${directionString} ${(interlocutorName).padEnd(8)} ${timestamp}`;
}
worker.ts
:
/// <reference no-default-lib="true" />
/// <reference lib="deno.worker" />
import {ExampleData, formatMessage} from './util.ts';
function handleMessageEvent (ev: MessageEvent<ExampleData>): void {
console.log(formatMessage('in', self.name, ev.data.sender, ev.data.timestamp));
const data: ExampleData = {sender: self.name, timestamp: Date.now()};
self.postMessage(data);
console.log(formatMessage('out', self.name, ev.data.sender, data.timestamp));
}
self.addEventListener('message', handleMessageEvent);
main.ts
:
// /// <reference lib="deno.unstable" />
import {ExampleData, formatMessage} from './util.ts';
function handleMessageEvent (this: Worker, ev: MessageEvent<ExampleData>): void {
console.log(formatMessage('in', 'main', ev.data.sender, ev.data.timestamp), '✅');
this.terminate();
}
// initialize static data once outside the loop
const specifier = new URL('./worker.ts', import.meta.url).href;
const options: WorkerOptions = {
type: 'module',
// deno: {namespace: true}, // requires deno run --unstable
};
for (let idx = 0; idx < 4; idx += 1) {
const workerName = `worker ${idx}`;
const worker = new Worker(specifier, {...options, name: workerName});
// in testing this example, registering the event listener after posting
// the first message didn't seem to chnage behavior, however it's safer to
// register before posting in order to ensure that registation happens
// prior to the event generated by the response
worker.addEventListener('message', handleMessageEvent);
const data: ExampleData = {sender: 'main', timestamp: Date.now()};
worker.postMessage(data);
console.log(formatMessage('out', 'main', workerName, data.timestamp));
}
运行示例:
/home/jesse/worker-example$ deno run --allow-read=. main.ts
Check file:///home/jesse/worker-example/main.ts
main post worker 0 1627390801087
Check file:///home/jesse/worker-example/worker.ts
main post worker 1 1627390801104
Check file:///home/jesse/worker-example/worker.ts
main post worker 2 1627390801122
Check file:///home/jesse/worker-example/worker.ts
main post worker 3 1627390801144
Check file:///home/jesse/worker-example/worker.ts
worker 0 receive main 1627390801087
worker 0 post main 1627390801776
main receive worker 0 1627390801776 ✅
worker 1 receive main 1627390801104
main receive worker 1 1627390801811 ✅
worker 1 post main 1627390801811
worker 3 receive main 1627390801144
main receive worker 3 1627390801873 ✅
worker 3 post main 1627390801873
worker 2 receive main 1627390801122
worker 2 post main 1627390801875
main receive worker 2 1627390801875 ✅
推荐阅读
- reactjs - 为什么我在尝试映射文件名列表时得到对象不支持属性或方法“映射”
- windows - USB设备连接AMAZON APPSTREAM2.0的问题
- python - 使用cookiecutter时如何省略花括号?
- javascript - 如何使用自己的 v-if (Vue) 避免子级的父级切换转换
- c# - 如何使用 g.net 提高 Emgu cv 中人脸检测的准确性
- c++ - C++ char array[] 内存泄漏
- angular - 更新到角度 10 后 NgxMaterialTimepickerFaceComponent 出错
- java - 关于单例范围和实例变量的问题
- reactjs - 在 Next.js 中动态导入模块时出现“forwardRef”错误
- javascript - 如何在 Blogger API v3 中正确使用 listByBlog?