【发布时间】:2015-09-15 21:23:05
【问题描述】:
假设我们创建了一个计时器setTimeout(f, 1000),然后创建了一个带有点击处理程序的按钮。如果在 setTimeout 之后没有同步代码运行,则“保证”点击处理程序在一秒钟内响应点击,将首先被调用。
但是,请考虑同步处理何时继续:
a_button.onclick = function () { console.log("ui") }
setTimeout(function () { console.log("timer") }, 1000)
s = Date.now()
while (Date.now() - s < 2000) { /* waste two seconds of CPU and block the UI */ }
有没有保证哪个事件会先发生
- .. 在一秒过去之前按下按钮?
- .. 在一秒后按下按钮?
也就是说,不同类型的事件排序根据它们“发生”的时间?
如果无法保证,行为是否会在浏览器之间发生变化,或者是否存在作案手法?
如果不保证 UI 事件,是否对 Web Workers 或 XHR 或图像 oncomplete 事件等有任何保证?
请提供涵盖或反驳此类保证的资源;或提出有力的反对意见,最好使用反例(以一种无需手动点击即可进行测试的方式,并且可能不正确地点击)。
在 yvesmancera 的评论中反思文章 "How JavaScript Timers Work" 之后,我想回答问题的否定(?)方面就足够了:
每个待处理的 UI 事件是否在个过期计时器之前处理?在其他种未决事件之前?
(Web Works | XHR | internal DOM)的事件是否在任何过期计时器之前处理?就计时器而言,这种行为是否与 UI 事件处理不同?这些事件相对于待处理的 UI 事件是如何排序的?
【问题讨论】:
-
John Resig,jQuery 的作者在这篇博文中解释了超时、间隔和异步回调是如何工作的,我强烈推荐它ejohn.org/blog/how-javascript-timers-work
-
@yvesmancera 感谢您的链接,读起来很有趣。特别是我想我在询问回调之间“队列中”事件的顺序 - 它是严格的队列还是优先级队列?它可以/它是否因浏览器而异?上面的示例有点做作(并且可能存在缺陷,但在 Chrome 中具有可重复的结果),并且对“何时发生”的定义保持开放。仅在计时器内,时间顺序就得到保证:
setTimeout(first, 0); setTimeout(second, 0)和(做一些小假设)setTimeout(second, 20); setTimeout(first, 10)。 -
规范声明它是一个列表:w3.org/TR/2011/WD-html5-20110525/timers.html 这意味着它们将按照一个接一个添加的顺序执行。
-
@zerkms 对于计时器来说,这很清楚,这实际上让我想到了这个问题;对于不同类型的事件(可以或不可以)如何交错,是否有类似的算法?我不应该在我之前的评论中使用“假设”,因为我小心翼翼地选择了这些值。
-
@user2864740 “交错”是什么意思?
标签: javascript events asynchronous