【问题标题】:How to get child worker send message to parent in Deno with multiple workers?如何让童工与多个工人一起向 Deno 中的父母发送消息?
【发布时间】:2021-07-27 21:13:05
【问题描述】:

我是工人新手,所以基于this 问题我正在尝试以下操作:

// 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" }

有人可以帮我解决我哪里出错了吗?为什么我只收到最后一个工人的回应,而不是每个工人的回应?

【问题讨论】:

    标签: web-worker deno


    【解决方案1】:

    有人可以帮我解决我哪里出错了吗?为什么我只收到最后一个工人的回应,而不是每个工人的回应?

    我怀疑这是因为您在 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 ✅
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-11
      • 2016-05-29
      • 2013-03-10
      相关资源
      最近更新 更多