【问题标题】:What happens to setTimeout when the computer goes to sleep?当计算机进入睡眠状态时,setTimeout 会发生什么?
【发布时间】:2011-09-14 20:48:58
【问题描述】:

在现代网络浏览器中,假设我执行setTimeout 10 分钟(12:00),5 分钟后让计算机进入睡眠状态,当系统再次唤醒时会发生什么?如果它在 10 分钟之前(12:09)或更晚(16:00)醒来会发生什么?

我问的原因是因为我希望每 10 分钟请求一次新的身份验证令牌,我不确定浏览器是否会做正确的事情并在唤醒时立即请求新令牌经过很长一段时间。

澄清:我不想使用 cookie - 我正在尝试在这里构建网络服务;是的,服务器将拒绝旧的和无效的令牌。

【问题讨论】:

  • 既然javascript是客户端,那么设置一个可以在特定时间过期的cookie不是更好吗?
  • stackoverflow.com/questions/3824754/… 建议,正如 Andrew 回答的那样,它不会起作用。
  • @daybreaker,当然 cookie 是可能的,但我正在尝试创建一个基于服务的应用程序。相同的服务为网络应用、iPhone 和 Android 应用提供服务。

标签: javascript settimeout


【解决方案1】:

该行为基于浏览器和操作系统。操作系统会处理睡眠,而个别应用通常不会考虑它。

最有可能发生的情况是,操作系统将在计时器上的剩余时间与关闭时相同的情况下重新启动。另一种可能性是它根本不会触发。

如果这确实是一个问题,您可能希望比抱歉更安全,并存储令牌初始化时间的时间戳,并使用setInterval 定期检查它(比如每分钟两次)。

但是,安全性不应该只是客户端的事情。如果使用旧的/无效的令牌,请确保您的服务器会引发错误,并且 Ajax 的行为会适当地响应。

[编辑] 我同意另一篇文章,它可能会在下一个刻度时立即触发。 Resig 的博文非常好。

【讨论】:

  • 服务器将拒绝旧令牌...我试图不向客户端显示不必要的错误...
  • 您实际上让我想到了我自己的应用程序在这种情况下的表现......这确实是一个好问题。我几乎想登录我的银行并尝试看看他们的行为。
  • 他们可能正在使用带有时间戳的 cookie。我在这里尝试使用无 cookie 服务,因此提出了问题。
  • 关于 Andrew 的编辑:它可能在唤醒时立即触发,但这取决于浏览器。
  • 例如,IE 10 会重新加载页面。
【解决方案2】:

John Resig's blog 中,据说计时器正在使用“挂钟”。我相信这些事件会在机器恢复后立即触发,因为 setTimeout() 不能保证执行是一个特定的时间点,而是在指定的时间间隔之后尽快执行。但是,我自己没有检查过。

【讨论】:

  • 您应该已经检查过了——它不是这样工作的,而且您基于 JR 博客的推断非常松散。它绝对不会跟随我测试过的任何系统上的挂钟。
  • FWIW,规范说:“等到与方法上下文关联的文档完全处于活动状态,再超时毫秒(不一定连续)”。这意味着可以在计算机休眠时暂停计时器。
【解决方案3】:

据我测试,它只是在计算机唤醒后停止并恢复。当计算机唤醒时,setInterval/setTimeout 不知道任何时间过去了。

我认为你不应该依赖setTimeout/Interval 的准确性来处理时间紧迫的事情。对于谷歌浏览器我discovered recently,如果激活它的选项卡失去焦点,任何超时/间隔(小于 1 秒)都将减慢到每秒一次。

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

因此,使用间隔和超时,根据由它启动的函数中的开始时间检查时间,可以提高准确性。现在,如果您从 12:00 开始,计算机进入睡眠状态并在 16:13 左右醒来,检查 16:13 和 12:00,您确定您必须更新令牌。使用时间比较的例子可以找到here

【讨论】:

  • 这也符合我的经验。
  • 我刚刚为此创建了一个快速测试。 FF 30 和 Chrome 35 可以在计算机恢复后立即触发长时间运行的超时。 IE 10 重新加载页面。小提琴@jsfiddle.net/Pegleg3941/8uhy8
  • the counter ticks on from the time the computer fell asleep.
  • 截至 2017 年 (Chrome 61),这种让计数器继续进入睡眠状态的行为没有改变。
  • 我认为这可以更清楚地表达:当计算机唤醒时,setInterval/setTimeout 并不知道任何时间过去了。
【解决方案4】:

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

//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);

【讨论】:

  • 这是一个很好的解决方案。非常适合我 - 谢谢。
  • 在我的情况下,只有当用户处于活动状态并且在最后一小时内没有空闲时,我才必须获取新令牌。所以从服务器令牌在 1 小时后过期,但在此之前我必须获取新令牌并更新 localStorage .如果用户处于非活动状态,则显示会话过期消息,否则静默获取新令牌
  • 内部setInterval()是什么原因?为什么是 5 秒?
【解决方案5】:

这是我的代码:

<!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.

【讨论】:

    【解决方案6】:

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

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

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

    【讨论】:

      【解决方案7】:

      根据 Ben 的回答,我创建了以下实用程序。您可以调整采样持续时间,但我就像这样使用它来刷新令牌:

      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);
      

      【讨论】:

        猜你喜欢
        • 2011-09-26
        • 2017-03-08
        • 1970-01-01
        • 1970-01-01
        • 2010-09-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多