有人可以帮我解决我哪里出错了吗?为什么我只收到最后一个工人的回应,而不是每个工人的回应?
我怀疑这是因为您在 postMessage 完成之前关闭了每个工人。在你的worker.ts:
self.postMessage(data)
self.close()
来自 MDN 页面DedicatedWorkerGlobalScope.close():
DedicatedWorkerGlobalScope 接口的close() 方法丢弃任何在DedicatedWorkerGlobalScope 的事件循环中排队的任务,从而有效地关闭了这个特定范围。
下面,我包含了对您的示例的重构,其中增加了一些类型安全性和更详细的日志记录,以便您可以查看更多事件和一些时间信息。在示例中,不是从每个工作人员内部调用self.close(),而是在接收到每条消息后(在我们完成工作人员之后)在主作用域的消息事件处理程序中调用Worker.terminate()。您可以忽略 triple-slash directives(尽管它们可能有助于在您的编辑器中进行类型检查)。
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 ✅