在任何浏览器中运行以下代码(多次尝试):
console.log('processing: task #1');
setTimeout(function(){
console.log('processing: task #3');
},0);
alert('See console logs');
console.log('processing: task #2');
根据我的理解,上面的代码会导致控制台输出:
"processing: task #1"
"processing: task #2"
"processing: task #3"
但在Firefox(v38.0.1)中,它会产生以下输出:
"processing: task #1"
"processing: task #3"
"processing: task #2"
请解释为什么Firefox会这样做。不知道它是否是一个bug或Firefox自己的标准。
您可以在此处看到现场演示:http://jsbin.com/cijonu
答案 0 :(得分:6)
这是一个错误。 HTML5规范不允许事件处理程序在显示警报时触发:
Section 6.1.4定义了事件循环。
在6.1.4.2中,本节还有助于提供有关事件触发顺序的一些保证(事件循环算法的第1点)以及在事件处理程序返回后呈现文档(第4.3点)< / SUP>
Section 6.4定义setTimeout
的计时器初始化步骤:
... 14. Queue任务
task
。
本节第12点还提供了关于多次超时的相对排序的保证 - 稍后发出的超时可能不会在之前发出的超时之前触发,除非它具有更短的超时
Section 6.5定义alert
行为。
可选择中止这些步骤。 (例如,用户代理可能会为用户提供忽略所有警报的选项,因此无论何时调用该方法,都会在此步骤中止。)
向用户显示给定的
message
。- 醇>
在等待用户确认消息时,可选择pause。
(注意:confirm
和prompt
必须暂停,因为它们会根据用户操作返回
暂停规范说:
由于历史原因,本规范中的某些算法要求用户代理在运行任务时暂停,直到满足条件目标。这意味着执行以下步骤:
...
3. 等到条件goal
满足。当用户代理具有暂停的任务时,相应的事件循环不能运行更多任务,并且当前正在运行的任务中的任何脚本都必须阻止。用户代理应该在暂停时保持对用户输入的响应,但是,尽管如此因为事件循环不会做任何事情而减少了容量。
(强调我的)
请注意,如果alert
没有暂停,控制台日志仍必须按顺序排列:首先同步执行完成(日志#2),然后超时触发(日志#3),然后用户关闭警报。正如页面javascript所观察到的,行为与用户立即关闭警报框的行为相同。
答案 1 :(得分:3)
这是一个Firefox错误。
我已在此处报告:https://bugzilla.mozilla.org/show_bug.cgi?id=1169568