【问题标题】:Is the order of setTimeout and non-timer (eg. UI) event callbacks guaranteed according to time?setTimeout 和非定时器(例如 UI)事件回调的顺序是否按时间保证?
【发布时间】: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


【解决方案1】:

正如specification 状态

  1. 等到此算法的任何调用在timeout 等于或小于此算法的调用完成之前开始。

这意味着如果实现符合规范要求,那么:

  1. setTimeout(first, 0); setTimeout(second, 0) --- 对于此代码,first 将始终在 second 之前触发

  2. setTimeout(second, 20); setTimeout(first, 10) --- 对于此代码,first 也将始终在 second 之前触发

在处理来自不同队列的事件时,another specification 表示:

  1. 在事件循环的任务队列之一上运行最旧任务,忽略关联文档未完全活动的任务。用户代理可以选择任何任务队列。

老实说,我并不清楚,因为“用户代理可以选择任何任务队列”。陈述。我认为它允许实现以任意顺序运行它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-20
    • 1970-01-01
    • 2019-04-16
    • 1970-01-01
    • 2022-01-22
    • 2017-07-10
    • 2019-08-25
    • 1970-01-01
    相关资源
    最近更新 更多