了解Web Worker中事件处理程序的作用域

时间:2019-05-28 08:09:04

标签: javascript event-handling web-worker

考虑以下来自以下网站的Webworker代码:https://www.html5rocks.com/en/tutorials/workers/basics/

网页:

<button onclick="sayHI()">Say HI</button>
<button onclick="unknownCmd()">Send unknown command</button>
<button onclick="stop()">Stop worker</button>
<output id="result"></output>

<script>
  function sayHI() {
    worker.postMessage({'cmd': 'start', 'msg': 'Hi'});
  }

  function stop() {
    // worker.terminate() from this script would also stop the worker.
    worker.postMessage({'cmd': 'stop', 'msg': 'Bye'});
  }

  function unknownCmd() {
    worker.postMessage({'cmd': 'foobard', 'msg': '???'});
  }

  var worker = new Worker('doWork2.js');

  worker.addEventListener('message', function(e) {
    document.getElementById('result').textContent = e.data;
  }, false);
</script>

然后在doWork2.js中:

self.addEventListener('message', function(e) {
  var data = e.data;
  switch (data.cmd) {
    case 'start':
      self.postMessage('WORKER STARTED: ' + data.msg);
      break;
    case 'stop':
      self.postMessage('WORKER STOPPED: ' + data.msg +
                       '. (buttons will no longer work)');
      self.close(); // Terminates the worker.
      break;
    default:
      self.postMessage('Unknown command: ' + data.msg);
  };
}, false);

因此,当您单击SayHi时,doWork2中定义的“消息”事件处理程序将首先接收该事件。然后,它将触发另一个“消息”事件,该事件由打印出消息的主页上定义的处理程序接收。

步骤流就是这样。

  1. 用户单击按钮,引发消息事件。
  2. doWork2中的处理程序已执行。
  3. doWork2中的处理程序引发消息事件
  4. 执行网页上的处理程序

请回答以下两个问题:

问题1::在上面的步骤2中,为什么触发了doWork2中的处理程序,但未触发页面上的处理程序?

问题2:在从doWork2触发事件后的第4步中,为什么页面上的处理程序被执行,但是doWork2中的处理程序没有递归执行?

2 个答案:

答案 0 :(得分:0)

之前触发doWorks2事件侦听器的原因是因为javascript解释代码的方式。 Java语言中的代码执行是在两个方向都有异步功能的情况下发生的。有一个调用堆栈,其中的命令以同步顺序或经典顺序运行,然后对于异步功能,有一个消息队列,该消息队列按事件的添加顺序将事件排队。

查看更多:https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop

答案 1 :(得分:0)

事实证明,在两个不同的对象上有两种postMessage实现。

问题1的答案

在调用worker.postMessage()时

  

...工作程序接口向工作程序的内部范围发送一条消息

因此页面上的消息事件处理程序看不到它。

问题2的答案

调用self.postMesssage时,self是工作程序的全局范围,其实现方式如下:

  

使用以下命令将信息发送回产生该信息的线程   DedicatedWorkerGlobalScope.postMessage方法。

因此,它不会递归调用自身,因为消息事件仅在产生它的线程中可见。

来源:https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage