javascript - 警报后使用 setTimeout 在 Firefox 中以错误顺序执行的代码

标签 javascript firefox settimeout alert

在任意浏览器中运行以下代码(多试几次):

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.4setTimeout 定义定时器初始化步骤:

... 14. Queue the task task.

本节的第 12 点还提供了关于多个超时的相对顺序的保证 - 稍后发出的超时可能不会在较早发出的超时之前触发,除非它有更短的超时

Section 6.5定义 alert 行为。

  1. 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.)

  2. Show the given message to the user.

  3. Optionally, pause while waiting for the user to acknowledge the message.

(注意:暂停对于 confirmprompt 是强制性的,因为它们基于用户操作返回)

暂停规范说:

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 condition goal 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/

相关文章:

javascript - 使用 setTimeout 循环播放视频

JavaScript setTimeout 无法访问函数变量

javascript - 使用表格的先前滚动条位置重新加载页面

javascript - 如何使用 Javascript 隐藏和显示基于特定 div 类基的多个 div?

javascript - 为什么 Firefox 在页面加载时触发 mouseenter 事件?

javascript - 在 Firefox 中,使用 Javascript 写入文件?

Javascript多维数组删除

javascript - 如何将自定义幻灯片中的图像居中

javascript - 时间显示 Nan :Nan in Firefox, Chrome 完美运行

javascript - 即使使用 setTimeout 和 promises 函数仍然执行