[英]WebKit setInterval and system time change
創建簡單任務時遇到以下問題:使用WebKit引擎顯示html時鍾。 附加要求是處理系統時間更改,並且該更改應在Windows上運行。 我已經使用setInterval達到了這個目的,但是在向后更改系統時間后,它似乎凍結了瀏覽器。 對我來說,它看起來像WebKit問題。 通過運行以下簡單代碼,可以輕松地在safari上重現代碼:
<p id="date"></p>
setInterval(SetTime, 1000);
function SetTime() {
document.getElementById('date').textContent=new Date();
}
之后,我使用了遞歸setTimeout調用的另一種方法。 效果一樣。
(function loop() {
document.getElementById('date').textContent=new Date();
setTimeout(loop, 1000);
})();
有什么想法為什么會發生以及如何解決這個問題?
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];
}
}
有了這種實現,想象一下現在將系統時間(即上述示例中的Date.now()
)更改為過去的值-計時器的時間戳仍將相對於先前的系統時間(即將來)進行設置。
setInterval
存在相同的問題(假設WebKit中使用合理的代碼)將使用setTimeout
實現。
不幸的是,這意味着setTimeout
或setInterval
任何調用都會受到影響。
或者,您可以使用可愛的window.requestAnimationFrame
方法在每個刻度上執行回調。 我根本沒有測試過,但是無論系統時間如何,它應該在每個刻度上繼續觸發。
另外,每次觸發回調時,您都會將當前時間戳作為參數傳遞。 通過跟蹤傳遞給回調的前一個時間戳,您可以輕松地檢測到系統時間的倒退:
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);
對於您來說,這可能不是個好消息,但是您可能應該重寫整個應用程序以使用requestAnimationFrame
似乎更適合您的需求:
var onNextFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame;
var dateElem = document.getElementById('date');
var updateDate = function(timestamp) {
dateElem.textContent = new Date();
onNextFrame(updateDate);
};
onNextFrame(updateDate);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.