我注意到如果我setTimeout
在未来设置为 1 分钟,然后将我的系统时间更改为过去的 5 分钟,该setTimeout
功能将在 6 分钟后触发。
我这样做是因为我想看看在夏令时更改系统时钟期间会发生什么。
我的 JavaScript 网页使用了一个setTimeout
功能,每 5 秒自动刷新一次页面,如果要进行夏令时,那么页面信息将冻结一个小时。有解决方法吗?
编辑:我正在使用 Ajax 更新页面,我不想刷新整个页面。
我注意到如果我setTimeout
在未来设置为 1 分钟,然后将我的系统时间更改为过去的 5 分钟,该setTimeout
功能将在 6 分钟后触发。
我这样做是因为我想看看在夏令时更改系统时钟期间会发生什么。
我的 JavaScript 网页使用了一个setTimeout
功能,每 5 秒自动刷新一次页面,如果要进行夏令时,那么页面信息将冻结一个小时。有解决方法吗?
编辑:我正在使用 Ajax 更新页面,我不想刷新整个页面。
使用setInterval
代替,setTimeout
你的问题应该得到解决:)
更新:
如果你真的不能使用 setTimeout 或 setInterval,你可以尝试隐藏iframe
一个加载一个简单的 HTML 页面,看起来像这样:
<html>
<head>
<meta http-equiv="refresh" content="300"/>
<script>
document.domain='same as parent page';
top.ajax_function_you_wish_to_trigger();
</script>
</head>
<body>
</body>
</html>
如果你幸运的话,元刷新不会给你带来同样的问题。
另一种解决方案是通过server push将事件触发移动到服务器。不这样做的原因有很多,尤其是您要集中事件并使它们成为服务器的负担,但它可以被认为是最后的手段。
我最近也遇到了这个问题。就我而言,时间变化可能会导致严重的经济损失,所以我必须认真对待。
一些背景:
setTimeout()
IE 和 Opera 可以正确处理系统时间更改(对,没有副作用setInterval()
)。我的解决方案:使用来自用户交互的一些事件(即mousemove
,mouseover
等)来触发时间更改检查。
Clock.prototype.checkLocalTime = function(){
var diff = Date.now()- this.lastTimestamp;
if ( diff < 0 || diff > 20000) { // if time shifted back or more than 20s to the future
console.warn('System time changed! By ' + diff + 'ms' );
this.restartTimer();
this.getServerTime();
}
this.lastTimestamp = time;
}
如您所见,我重新启动计时器并另外与服务器同步时间。
我发现使用window.performance给了我更准确的结果,并在系统时间发生变化时保持一致。
我用它作为在 setInterval 刻度内获取当前时间的一种方法,这样倒计时计时器就不会受到系统时间更改的影响。我根据给定时间的滴答数来计算它,以尝试通过更改系统时钟来防止在计时器上作弊(获得更多时间)
getCurrentTime = () => {
return window.performance ?
performance.timing.navigationStart + performance.now() : Date.now();
}
tick() {
let now = this.getCurrentTime();
if (this.calibrateTime) { //calibrate with a given server time
now -= this.timeCalibration;
}
const elapsedSeconds = (now - this.startedAt) / 1000;
if (elapsedSeconds > this.props.timeLimit + this.props.submitBuffer) {
clearInterval(this.interval);
this.props.onTimeUp();
}
let secondsRemaining = this.props.timeLimit - Math.floor(elapsedSeconds);
if (secondsRemaining < 0) secondsRemaining = 0;
}
startTimer() {
if (!this.startedAt) {
this.startedAt = Date.now();
}
this.setState({ started: true }, () => {
this.interval = setInterval(this.tick.bind(this), 500);
});
}
您可以使用元标记刷新来执行此操作。此代码将每 5 秒刷新一次页面:
<meta http-equiv="refresh" content="5">
至于javascript问题,它可能只是浏览器处理setTimeout的方式。它告诉浏览器在设定的时间执行代码,然后当时钟改变时,代码仍然在时钟改变之前的时间执行?只是一个猜测,但我下次使用 setTimeout 时必须记住这一点。
编辑:好的,这不适用于 ajax 再次编辑:这是一个非常好的问题。我确信 setTimeout 的功能正如我上面所说的那样,但是哇,这是一个脑筋急转弯。
您可以捏造并进行if (Date in range foo)
检查。基本上检查当前时间戳是否在夏令时的 5 秒内,然后立即刷新页面,而不是使用setTimeout
.
这样,用户在已知时间变化附近会感到轻微的烦恼,但页面不会冻结一个小时。