当计算机进入睡眠状态时,setTimeout会怎样?


75

在现代的Web浏览器中,假设我做了setTimeout10分钟(在12:00),然后5分钟使计算机进入睡眠状态,当系统再次唤醒时会发生什么?如果在10分钟结束前(12:09)或更晚之后(16:00)醒来,会怎样?

我问的原因是因为我想每10分钟请求一个新的身份验证令牌,而且我不确定浏览器是否会执行正确的操作,如果很长一段时间后唤醒它会立即请求一个新的令牌时间。

说明:我不希望使用Cookie-我正在尝试在此处构建Web服务;是的,服务器将拒绝旧的无效令牌。


1
由于javascript是客户端,因此设置可以在特定时间到期的cookie会更好吗?
破晓

stackoverflow.com/questions/3824754/…就像安德鲁回答的那样,建议它不起作用。
Sysyphus 2011年

@daybreaker,可以使用cookie,但是我正在尝试创建一个基于服务的应用程序。Web服务,iPhone和Android应用程序都可以使用相同的服务。
Sudhir Jonathan

Answers:


61

据我测试,它只是在计算机唤醒后停止并恢复。我想这意味着一次会话,具体取决于setTimeout/Interval计算机进入睡眠状态以来计数器的滴答声。

我认为您不应该依赖于setTimeout/Interval时间紧迫性问题的准确性。对于谷歌浏览器,我最近发现,如果激活的标签页失去了焦点,则任何超时/间隔(短于1秒)都将减慢至每秒一次。

除此之外,超时/间隔的准确性还取决于其他正在运行的函数等。简而言之:它不是很准确。

因此,使用间隔和超时,将时间与由其启动的函数中的启动时间进行对照可以提高精度。现在,如果您从12:00开始,计算机将进入睡眠状态,并在16:13左右醒来,将12:00与16:13进行比较,您确定必须更新令牌。在此处可以找到使用时间比较的示例


1
这也符合我的经验。
jwl 2012年

我为此创建了一个快速测试。FF 30和Chrome 35在计算机恢复后可以合理触发长时间运行的超时。IE 10重新加载页面。小提琴@ jsfiddle.net/Pegleg3941/8uhy8
EpicVoyage 2014年

the counter ticks on from the time the computer fell asleep.<-我的经验也是如此。
曼恩2014年

1
截至2017年(Chrome 61),这种让计数器继续入睡的行为并未改变。
Erez Cohen

6
我认为这可以用更清楚的措词来表达:当计算机唤醒setInterval / setTimeout时,它不知道任何时间过去了。
cdosborn

8

将当前日期时间与页面加载时的日期时间进行比较,如下所示:

//Force refresh after x minutes.
var initialTime = new Date();
var checkSessionTimeout = function () {
    var minutes = Math.abs((initialTime - new Date()) / 1000 / 60);
    if (minutes > 20) {
        setInterval(function () { location.href = 'Audit.aspx' }, 5000)
    } 
};
setInterval(checkSessionTimeout, 1000);

这是一个很好的解决方案。对我来说真的很好-谢谢。
BeesonBison

在我的情况下,只有当用户处于活动状态并且在上一小时内没有空闲时,我才必须获取新令牌。因此,从服务器令牌中过期1小时之后,但在此之前我必须获取新令牌并更新localStorage。如果用户处于非活动状态,则显示会话已过期消息,否则静默获取新令牌
Cyber​​Abhay

内部setInterval()的原因是什么?为什么要5秒?
robsch

7

这是我的代码:

<!doctype html>
<html>

<body>
<input type="button" name="clickMe" id="colourButton" value="Start Timer" onclick="setTimeout('alert(\'Surprise!\')', 120000)"/>

</body>
<script>


</script>
</html>

我采用了三种可能回答该问题的方案。

方案1:00秒后,单击“启动计时器”按钮。25秒后,计算机进入睡眠状态。在1分钟40秒时唤醒计算机。在2分钟时显示警报。

方案2:在00秒处,单击“启动计时器”按钮。26秒时计算机进入睡眠状态。3分钟后,我唤醒了计算机。显示警报。

场景3:这真是令人震惊。

<input type="button" name="clickMe" id="colourButton" value="Start Timer" onclick="setTimeout('alert(\'Surprise!\')', 600000)"/>

在00秒时,我单击“开始计时器”按钮。大约1分30秒,计算机进入休眠模式(我的电脑需要一分钟才能启动休眠模式)

8分钟后,我打开笔记本电脑。恰好在10分钟时,警报弹出。

PS: This is my first ever comment on Stack Exchange. I prefer to execute code and view results rather than infer from theory.

5

该行为基于浏览器和操作系统。操作系统处理睡眠,单个应用程序通常无法解决。

最有可能发生的情况是,操作系统将在关机时与计时器保持相同的时间恢复运行。另一种可能性是它根本不会触发。

如果确实有问题,您可能希望比后悔更安全,并存储令牌初始化和使用时间的时间戳记 setInterval定期检查(例如每分钟两次)。

但是,安全性不应该只是客户端的事情。如果使用了旧的/无效的令牌,请确保服务器抛出错误,并且Ajax的响应方式正确。

[edit]我同意其他帖子,它可能会在下一个滴答中立即触发。Resig的博客文章非常好。


服务器将拒绝一个较旧的令牌...我试图不向客户端不必要地显示错误...
Sudhir Jonathan

您实际上让我思考了在这种情况下我自己的应用程序的行为……这确实是一个好问题。我几乎想登录我的银行并尝试查看其行为。
Andrew Curioso 2011年

他们可能正在使用带有时间戳的cookie。我正在尝试使用无cookie服务,因此出现了问题。
Sudhir Jonathan

关于安德鲁(Andrew)的修改:唤醒后可能立即触发,但这取决于浏览器。
EpicVoyage 2014年

例如,IE 10重新加载该页面。
EpicVoyage 2014年

4

根据Ben的回答,我创建了以下util。您可以调整采样持续时间,但是我将其像这样用于令牌刷新:

const absoluteSetInterval = (handler, timeout) => {
  let baseTime = Date.now();
  const callHandler = () => {
    if (Date.now() - baseTime > timeout) {
      baseTime = Date.now();
      handler();
    }
  };
  return window.setInterval(callHandler, 1000);
};

const absoluteClearInterval = (handle) => window.clearInterval(handle);

2

JavaScript计时器(setTimeout)在几种情况下的行为。

  1. 当线程空闲并且超时触发时:超时后立即触发计时器。它可能具有大约0-5毫秒的不精确度(典型情况)。
  2. 当线程超级繁忙(巨大循环)的时间足以通过计时器超时时:释放线程后立即执行计时器。
  3. 出现警报时:与2相同。
  4. 当线程由于笔记本电脑进入睡眠状态而暂停时:我已经看到了几件事。但是最常见的是完全不准确,并且忽略了睡眠时间。

由于JavaScript中的计时器基于CPU滴答,并且CPU处于睡眠状态,因此计时器完全暂停并恢复为“因为什么也不会发生”。


-2

John Resig的博客中,计时器被称为使用“挂钟”。我相信事件将在计算机恢复后立即触发,因为setTimeout()不能保证执行是特定的时间点,但不能保证在指定的时间间隔后尽快执行。但是,我自己还没有检查过。


10
您应该已经检查了它-这样无法正常工作,并且根据JR的博客所做的推断非常松散。在我测试过的任何系统上,它绝对不会遵循挂钟。
jwl 2012年

2
FWIW,规范说:“等到与方法上下文关联的Document完全活动了又一个超时毫秒(不一定是连续的)”。这意味着在计算机休眠时可以暂停计时器。
geon 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.