Javascript WebKit设置间隔和系统时间更改
我在创建简单任务时遇到了以下问题:使用WebKit引擎显示html时钟。额外的要求是处理系统时间变化,并且它应该在Windows上工作。 我已经使用setInterval实现了这一点,但在我向后更改系统时间后,它似乎冻结了浏览器。 对我来说,这看起来像是WebKit的问题。通过运行以下简单代码,在safari上很容易复制:Javascript WebKit设置间隔和系统时间更改,javascript,webkit,Javascript,Webkit,我在创建简单任务时遇到了以下问题:使用WebKit引擎显示html时钟。额外的要求是处理系统时间变化,并且它应该在Windows上工作。 我已经使用setInterval实现了这一点,但在我向后更改系统时间后,它似乎冻结了浏览器。 对我来说,这看起来像是WebKit的问题。通过运行以下简单代码,在safari上很容易复制: <p id="date"></p> setInterval(SetTime, 1000); function SetTime() { document
<p id="date"></p>
setInterval(SetTime, 1000);
function SetTime() {
document.getElementById('date').textContent=new Date();
}
你知道为什么会发生这种情况以及如何解决吗?这几乎肯定是WebKit的问题 问题 当您使用
setTimeout
时,您将创建一个具有两个属性的“计时器”:
- 时间戳,设置为现在+指定的延迟
- 当系统时间大于时间戳时,将触发一次回调
setTimeout
的一个幼稚的实现如下所示:
var timers = [];
function setTimeout(callback, delay) {
var id = timers.length;
timers[id] = {
callback: callback,
timestamp: Date.now() + delay
}
return id;
}
这只需创建一个计时器并将其添加到列表中。然后,JS运行时将在每次勾选时检查这些计时器,并对已触发的计时器执行回调:
var now = Date.now();
for(var id in timers) {
var timer = timers[id];
if(timer && timer.timestamp < now) {
callback();
delete timers[id];
}
}
结论
这对您来说可能不是什么好消息,但您可能应该重写整个应用程序以使用requestAnimationFrame
——它似乎更适合您的需要:
var onNextFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame;
var dateElem = document.getElementById('date');
var updateDate = function(timestamp) {
dateElem.textContent = new Date();
onNextFrame(updateDate);
};
onNextFrame(updateDate);
谢谢你,吉姆。我会试试你的解决办法。我已经向WebKit团队报告了这个问题。很高兴为您服务。请让我知道这是否有效(如果有效,请接受答案)!
var lastTimestamp;
var onNextFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame;
var checkForPast = function(timestamp) {
if(lastTimestamp && timestamp < lastTimestamp) {
console.error('System time moved into the past! I should probably handle this');
}
lastTimestamp = timestamp;
onNextFrame(checkForPast);
};
onNextFrame(checkForPast);
var onNextFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame;
var dateElem = document.getElementById('date');
var updateDate = function(timestamp) {
dateElem.textContent = new Date();
onNextFrame(updateDate);
};
onNextFrame(updateDate);