setTimeout 跨 OS sleep/suspend 的行为是否已定义?
Is the behaviour of setTimeout across an OS sleep/suspend defined?
我设置了一个 setTimeout
例如 10s,在这 10s 期间,我 suspend/sleep PC。醒来时,下列哪项是正确的:-
- 超时保证触发
- 超时保证不触发
- 超时可能会或可能不会触发。它是特定于浏览器的
重复设置间隔的相同问题。是否保证(不)继续
据我目前所读的内容,
- 保证火爆
但是,延迟不能保证,可能取决于各种因素,并且因浏览器而异。
人们已经测试了这种行为。
您可能还想看看 John Resig 的以下 cross-post. An interesting read。
简答
它被定义为在规范中执行。超时请求将进入各种队列并进行轮询,直到它被触发。如果系统在恢复时休眠,它将从停止的地方开始并恢复轮询。
长答案 可能比任何人想知道的都多
最近的(2014 年 10 月 28 日)working-draft of the Timer's Spec 在 w3 写的答案时,它会触发...只要 OS 不乱-在前往 sleep/suspending 和 waking/resuming(范围外部)的过程中。这更像是一个 OS 级别的问题,但就 w3 规范而言,它最终会被触发。
setInterval(...)
和 setTimeout(...)
都来自浏览器的 window
对象实现的相同 windowTimer
接口。
在这两种情况下,客户端定义了一个间隔或超时请求,方法上下文对其进行 timer initialization steps
添加到 活动计时器列表 并为计划的 任务 返回 句柄。
一旦进入活动计时器列表,系统会将任务排队,以便在请求的持续时间或之后执行(挂起其他具有更高优先级的任务以及 CPU 负载)。如果一个任务不能预留 CPU 时间,它将 poll/wait 直到它可以。因此,如果系统在恢复时休眠,它将从中断的地方继续。
为了执行任务,句柄 必须存在于活动计时器列表 中。在任务有 运行 之后,如果重复标志设置为真(如果它是用 setInterval(...)
创建的), 任务 将使用相同的参数重新创建并分配完全相同的 句柄。换句话说,它被添加回 queue/list 以在下一个时间间隔或之后执行。
以下是 Timer
规范中关于系统从活动计时器列表中删除项目的唯一说明或评论:
Once the task has been processed, if the repeat flag is false, it is safe to remove the entry for handle from the list of active timers (there is no way for the entry's existence to be detected past this point, so it does not technically matter one way or the other)
根据规范,当任务为 运行 时,如果它在 list of active timers
中,它将按预期触发。否则它被中止。所以回到我的第一点,如果 OS 在恢复 任务 时在 sleep/suspend 过程中没有搞砸,则继续轮询。一旦它得到 CPU 时间,它的 handle 应该仍然存在于 活动定时器列表 中,因此在被处理后将执行。
我刚刚用这个脚本测试了它:
<html>
<body>
<script>
var d = 120;
var start = new Date ();
document.write(start + " : sleeping for " + d + " seconds");
</script>
<div id='result'><div>
<script>
function cb() {
var now = new Date ();
document.getElementById("result").innerHTML = "" + Date () + " : callback fired after " + (now.getTime() - start.getTime()) / 1000 + " seconds";
};
window.setTimeout(cb, d * 1000);
</script>
</body>
</html>
我在 Firefox 37.0.1 和 Chromium 41.0.2272.118(64 位)中打开了该页面,然后暂停了我的机器几分钟。当我恢复时,两个浏览器都等待了几分钟,即使计时器到期了。示例输出(机器在 Wed 15 Apr 17:52:11 BST 2015
恢复):
Wed Apr 15 2015 17:49:13 GMT+0100 (BST) : sleeping for 120 seconds
Wed Apr 15 2015 17:53:47 GMT+0100 (BST) : callback fired after 273.705 seconds
我设置了一个 setTimeout
例如 10s,在这 10s 期间,我 suspend/sleep PC。醒来时,下列哪项是正确的:-
- 超时保证触发
- 超时保证不触发
- 超时可能会或可能不会触发。它是特定于浏览器的
重复设置间隔的相同问题。是否保证(不)继续
据我目前所读的内容,
- 保证火爆
但是,延迟不能保证,可能取决于各种因素,并且因浏览器而异。 人们已经测试了这种行为。
您可能还想看看 John Resig 的以下 cross-post. An interesting read。
简答
它被定义为在规范中执行。超时请求将进入各种队列并进行轮询,直到它被触发。如果系统在恢复时休眠,它将从停止的地方开始并恢复轮询。
长答案 可能比任何人想知道的都多
最近的(2014 年 10 月 28 日)working-draft of the Timer's Spec 在 w3 写的答案时,它会触发...只要 OS 不乱-在前往 sleep/suspending 和 waking/resuming(范围外部)的过程中。这更像是一个 OS 级别的问题,但就 w3 规范而言,它最终会被触发。
setInterval(...)
和 setTimeout(...)
都来自浏览器的 window
对象实现的相同 windowTimer
接口。
在这两种情况下,客户端定义了一个间隔或超时请求,方法上下文对其进行 timer initialization steps
添加到 活动计时器列表 并为计划的 任务 返回 句柄。
一旦进入活动计时器列表,系统会将任务排队,以便在请求的持续时间或之后执行(挂起其他具有更高优先级的任务以及 CPU 负载)。如果一个任务不能预留 CPU 时间,它将 poll/wait 直到它可以。因此,如果系统在恢复时休眠,它将从中断的地方继续。
为了执行任务,句柄 必须存在于活动计时器列表 中。在任务有 运行 之后,如果重复标志设置为真(如果它是用 setInterval(...)
创建的), 任务 将使用相同的参数重新创建并分配完全相同的 句柄。换句话说,它被添加回 queue/list 以在下一个时间间隔或之后执行。
以下是 Timer
规范中关于系统从活动计时器列表中删除项目的唯一说明或评论:
Once the task has been processed, if the repeat flag is false, it is safe to remove the entry for handle from the list of active timers (there is no way for the entry's existence to be detected past this point, so it does not technically matter one way or the other)
根据规范,当任务为 运行 时,如果它在 list of active timers
中,它将按预期触发。否则它被中止。所以回到我的第一点,如果 OS 在恢复 任务 时在 sleep/suspend 过程中没有搞砸,则继续轮询。一旦它得到 CPU 时间,它的 handle 应该仍然存在于 活动定时器列表 中,因此在被处理后将执行。
我刚刚用这个脚本测试了它:
<html>
<body>
<script>
var d = 120;
var start = new Date ();
document.write(start + " : sleeping for " + d + " seconds");
</script>
<div id='result'><div>
<script>
function cb() {
var now = new Date ();
document.getElementById("result").innerHTML = "" + Date () + " : callback fired after " + (now.getTime() - start.getTime()) / 1000 + " seconds";
};
window.setTimeout(cb, d * 1000);
</script>
</body>
</html>
我在 Firefox 37.0.1 和 Chromium 41.0.2272.118(64 位)中打开了该页面,然后暂停了我的机器几分钟。当我恢复时,两个浏览器都等待了几分钟,即使计时器到期了。示例输出(机器在 Wed 15 Apr 17:52:11 BST 2015
恢复):
Wed Apr 15 2015 17:49:13 GMT+0100 (BST) : sleeping for 120 seconds
Wed Apr 15 2015 17:53:47 GMT+0100 (BST) : callback fired after 273.705 seconds