Javascript 当计算机进入睡眠状态时 setTimeout 会发生什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6346849/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 21:21:20  来源:igfitidea点击:

What happens to setTimeout when the computer goes to sleep?

javascriptsettimeout

提问by Sudhir Jonathan

In a modern web browser, suppose I do a setTimeoutfor 10 minutes (at 12:00), and 5 minutes later put the computer to sleep, what should happen when the system wakes up again? What happens if it wakes up before the 10 minutes are up (at 12:09) or much later (at 16:00)?

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

The reason I'm asking is because I'd like to have a new authentication token requested every 10 minutes, and I'm not sure if the browser will do the right thing and immediately request a new token if it wakes up after a long time.

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

Clarifications: I don't wan't to use cookies - I'm trying to build a web service here; and yes, the server will reject old and invalid tokens.

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

采纳答案by KooiInc

As far as I've tested, it just stops and resumes after the computer wakes up. I suppose that means for a session depending on setTimeout/Intervalthe counter ticks on from the time the computer fell asleep.

据我测试,它只是在计算机唤醒后停止并恢复。我想这意味着一个会话取决于setTimeout/Interval从计算机入睡时开始的计数器滴答声。

I don't think you should rely on the accuracy of setTimeout/Intervalfor time critical stuff. For google chrome I discovered recentlythat any timeout/interval (that is shorter than 1s) will be slowed down to once a second if the tab where it's activated looses focus.

我认为你不应该依赖于setTimeout/Interval时间关键的东西的准确性。对于谷歌浏览器,我最近发现,如果激活它的选项卡失去焦点,任何超时/间隔(短于 1 秒)都会被减慢到每秒一次。

Apart from that the accuracy of timeouts/intervals is dependent on other functions running etc. In short: it's not very accurate.

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

So using interval and timeouts, checking the time against a starttime within the function started by it would give you better accuracy. Now if you start at 12:00, the computer goes to sleep and wakes up at 16:13 or so, checking 16:13 against 12:00 you are certain you have to renew the token. An example of using time comparison can be found here

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

回答by Ben

Compare current datetime against datetime when the page was loaded, like so:

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

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

回答by DannyBoi

Here is my code :

这是我的代码:

<!doctype html>
<html>

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

</body>
<script>


</script>
</html>

I have taken three scenarios that might answer the question.

我已经采取了三个可能回答这个问题的场景。

Scenario 1:At 00 Seconds click on 'Start Timer' button . At 25 seconds computer falls asleep. At 1min 40 seconds wake up computer. At 2mins Alert is displayed.

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

Scenario 2 :At 00 Seconds click on 'Start Timer' button . At 26 seconds computer falls asleep. At 3 mins, I wakeup the computer. The Alert is displayed.

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

Scenario 3 :This one is truly astounding.

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

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

At 00 Seconds I click on 'Start Timer' button. At around 1min 30 seconds the computer is on hibernate mode (my pc takes a minute to initiate hibernate)

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

At 8 mins I turn the laptop on. At 10 mins exactly, the alert pops up.

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.

回答by Andrew Curioso

The behavior is based on both the browser and the operating system. The OS handle sleep and individual apps often don't account for it.

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

What will most likely happen is that the OS will come back up with the same time remaining on the timer as when it was shut down. The other possibility is that it won't fire at all.

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

If it is really a concern, you will probably want to be better safe than sorry and store a time stamp of when the token was initialized and use setIntervalto check it periodically (say twice a minute).

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

However, security should not be just a client side thing. Make sure that your server throws an error if an old / invalid token is used and that the Ajax behaves appropriately in response.

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

[edit] I agree with the other post that it might fire immediately on the next tick. Resig's blog post is very good.

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

回答by Erez Cohen

Based on Ben's answer, I created the following util. You can tweak the sampling duration, however I use it just like this for token refreshing:

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

回答by José Cabo

Behaviour of JavaScript timers (setTimeout) in several scenarios.

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

  1. When the thread is free and the timeout fires: The timer is fired immediately after the timeout. It might have certain imprecision of about 0-5 ms (typical scenario).
  2. When the thread is super busy (huge loop) long enough to pass the timer timeout: The timer will be executed immediately after the thread is freed.
  3. When there is an alert: Same behaviour as 2.
  4. When the thread is paused because our laptop went to sleep: I have seen several things. But most common is total inaccuracy and ignore of the time spent during sleeping.
  1. 当线程空闲并且超时触发时:定时器在超时后立即触发。它可能具有大约 0-5 ms 的某些不精确性(典型场景)。
  2. 当线程超级忙(巨大的循环)足够长以通过计时器超时时: 线程被释放后将立即执行计时器。
  3. 当有警报时:与 2 相同的行为。
  4. 当线程因为我们的笔记本电脑进入睡眠而暂停时:我看到了几件事。但最常见的是完全不准确和忽略睡眠时间。

Since timers in JavaScript are based on CPU ticks, and the CPU is sleeping, then the timer is completely paused and resumed as 'since nothing would have happen'.

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

回答by Evgeny Shadchnev

In John Resig's blogthe timers are said to be using "wall clock". I believe that the events will fire immediately after the machine is resumed because setTimeout() doesn't guarantee an execution is a specific point in time but as soon as possible after the specified interval. However, I haven't checked it myself.

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