了解 Web Worker 中事件处理程序的范围
Understanding scoping of event handlers in web workers
考虑以下 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 中定义的 "message" 事件处理程序首先获取该事件。然后它触发另一个 "message" 事件,该事件由打印消息的主页上定义的处理程序拾取。
步骤流程是这样的。
- 用户单击按钮,引发消息事件。
- 执行doWork2中的handler
- doWork2 中的处理程序引发消息事件
- 网页上的处理程序被执行
请回答以下 2 个问题:
问题一:上面第2步中为什么触发了doWork2中的handler,而页面上的handler却没有?
问题2:doWork2触发事件后的第4步,为什么页面上的handler执行了,doWork2中的handler却没有递归执行?
doWorks2 事件侦听器之前被触发的原因是因为 javascript 解释您的代码的方式。 Javascript 中的代码执行发生在 2 个方向的异步函数的情况下。有一个调用堆栈,其中包含 运行 按同步顺序或经典顺序排列的命令,然后对于异步函数,有一个消息队列,它按事件添加的顺序对事件进行排队。
查看更多:https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop
原来在两个不同的对象上有两个postMessage的实现。
问题 1 的答案
调用worker.postMessage()时
...the Worker interface sends a message to the worker's inner scope
因此页面上的消息事件处理程序看不到它。
问题 2 的答案
当调用 self.postMesssage 时,self
是 worker 的全局作用域,其实现如下:
sends back information to the thread that spawned it using the
DedicatedWorkerGlobalScope.postMessage
method.
因此它不会递归调用自身,因为消息事件仅在生成它的线程中可见。
来源:https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage
考虑以下 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 中定义的 "message" 事件处理程序首先获取该事件。然后它触发另一个 "message" 事件,该事件由打印消息的主页上定义的处理程序拾取。
步骤流程是这样的。
- 用户单击按钮,引发消息事件。
- 执行doWork2中的handler
- doWork2 中的处理程序引发消息事件
- 网页上的处理程序被执行
请回答以下 2 个问题:
问题一:上面第2步中为什么触发了doWork2中的handler,而页面上的handler却没有?
问题2:doWork2触发事件后的第4步,为什么页面上的handler执行了,doWork2中的handler却没有递归执行?
doWorks2 事件侦听器之前被触发的原因是因为 javascript 解释您的代码的方式。 Javascript 中的代码执行发生在 2 个方向的异步函数的情况下。有一个调用堆栈,其中包含 运行 按同步顺序或经典顺序排列的命令,然后对于异步函数,有一个消息队列,它按事件添加的顺序对事件进行排队。
查看更多:https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop
原来在两个不同的对象上有两个postMessage的实现。
问题 1 的答案
调用worker.postMessage()时
...the Worker interface sends a message to the worker's inner scope
因此页面上的消息事件处理程序看不到它。
问题 2 的答案
当调用 self.postMesssage 时,self
是 worker 的全局作用域,其实现如下:
sends back information to the thread that spawned it using the
DedicatedWorkerGlobalScope.postMessage
method.
因此它不会递归调用自身,因为消息事件仅在生成它的线程中可见。
来源:https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage