在任意浏览器中运行以下代码(多试几次):
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还是火狐自己的标准。
您可以在此处观看现场演示:http://jsbin.com/cijonu
最佳答案
这是一个错误。 HTML5 规范不允许在显示警报时触发事件处理程序:
Section 6.1.4定义事件循环。
在 6.1.4.2 中,本节还有助于提供一些关于事件触发顺序的保证(事件循环算法的第 1 点)以及在事件处理程序返回后呈现文档(第 4.3 点)
Section 6.4为 setTimeout
定义定时器初始化步骤:
... 14. Queue the task
task
.
本节的第 12 点还提供了关于多个超时的相对顺序的保证 - 稍后发出的超时可能不会在较早发出的超时之前触发,除非它有更短的超时
Section 6.5定义 alert
行为。
Optionally, abort these steps. (For example, the user agent might give the user the option to ignore all alerts, and would thus abort at this step whenever the method was invoked.)
Show the given
message
to the user.Optionally, pause while waiting for the user to acknowledge the message.
(注意:暂停对于 confirm
和 prompt
是强制性的,因为它们基于用户操作返回)
暂停规范说:
Some of the algorithms in this specification, for historical reasons, require the user agent to pause while running a task until a condition goal is met. This means running the following steps:
...
3. Wait until the conditiongoal
is met. While a user agent has a paused task, the corresponding event loop must not run further tasks, and any script in the currently running task must block. User agents should remain responsive to user input while paused, however, albeit in a reduced capacity since the event loop will not be doing anything.
(强调我的)
请注意,如果 alert
没有暂停,控制台日志仍必须按顺序排列:首先同步执行完成(log #2),然后超时触发(log #3),然后用户关闭警报。正如页面 javascript 所观察到的,行为与用户立即关闭警告框一样。
关于javascript - 警报后使用 setTimeout 在 Firefox 中以错误顺序执行的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30523412/