在现代的Web浏览器中,假设我做了setTimeout
10分钟(在12:00),然后5分钟使计算机进入睡眠状态,当系统再次唤醒时会发生什么?如果在10分钟结束前(12:09)或更晚之后(16:00)醒来,会怎样?
我问的原因是因为我想每10分钟请求一个新的身份验证令牌,而且我不确定浏览器是否会执行正确的操作,如果很长一段时间后唤醒它会立即请求一个新的令牌时间。
说明:我不希望使用Cookie-我正在尝试在此处构建Web服务;是的,服务器将拒绝旧的无效令牌。
在现代的Web浏览器中,假设我做了setTimeout
10分钟(在12:00),然后5分钟使计算机进入睡眠状态,当系统再次唤醒时会发生什么?如果在10分钟结束前(12:09)或更晚之后(16:00)醒来,会怎样?
我问的原因是因为我想每10分钟请求一个新的身份验证令牌,而且我不确定浏览器是否会执行正确的操作,如果很长一段时间后唤醒它会立即请求一个新的令牌时间。
说明:我不希望使用Cookie-我正在尝试在此处构建Web服务;是的,服务器将拒绝旧的无效令牌。
Answers:
据我测试,它只是在计算机唤醒后停止并恢复。我想这意味着一次会话,具体取决于setTimeout/Interval
计算机进入睡眠状态以来计数器的滴答声。
我认为您不应该依赖于setTimeout/Interval
时间紧迫性问题的准确性。对于谷歌浏览器,我最近发现,如果激活的标签页失去了焦点,则任何超时/间隔(短于1秒)都将减慢至每秒一次。
除此之外,超时/间隔的准确性还取决于其他正在运行的函数等。简而言之:它不是很准确。
因此,使用间隔和超时,将时间与由其启动的函数中的启动时间进行对照可以提高精度。现在,如果您从12:00开始,计算机将进入睡眠状态,并在16:13左右醒来,将12:00与16:13进行比较,您确定必须更新令牌。在此处可以找到使用时间比较的示例
the counter ticks on from the time the computer fell asleep.
<-我的经验也是如此。
将当前日期时间与页面加载时的日期时间进行比较,如下所示:
//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);
这是我的代码:
<!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.
该行为基于浏览器和操作系统。操作系统处理睡眠,单个应用程序通常无法解决。
最有可能发生的情况是,操作系统将在关机时与计时器保持相同的时间恢复运行。另一种可能性是它根本不会触发。
如果确实有问题,您可能希望比后悔更安全,并存储令牌初始化和使用时间的时间戳记 setInterval
定期检查(例如每分钟两次)。
但是,安全性不应该只是客户端的事情。如果使用了旧的/无效的令牌,请确保服务器抛出错误,并且Ajax的响应方式正确。
[edit]我同意其他帖子,它可能会在下一个滴答中立即触发。Resig的博客文章非常好。
根据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);
在John Resig的博客中,计时器被称为使用“挂钟”。我相信事件将在计算机恢复后立即触发,因为setTimeout()不能保证执行是特定的时间点,但不能保证在指定的时间间隔后尽快执行。但是,我自己还没有检查过。