一直困扰着我的是setTimeout()
Javascript中的方法多么难以预测.
根据我的经验,计时器在很多情况下非常不准确.由于不准确,我的意思是实际延迟时间似乎或多或少变化250-500ms.虽然这不是一个大量的时间,但当使用它来隐藏/显示UI元素时,时间可以明显地显着.
是否有任何技巧可以确保setTimeout()
准确执行(不使用外部API)或这是一个失败的原因?
是否有任何技巧可以确保
setTimeout()
准确执行(不使用外部API)或这是一个失败的原因?
不,不.你不会接近完全准确的计时器setTimeout()
- 浏览器没有为此设置.但是,您也不需要依赖它来计时.大多数动画库在几年前就已经解决了这个问题:你设置了一个回调setTimeout()
,但是根据(new Date()).milliseconds
(或等价物)的值确定需要做什么.这使您可以在较新的浏览器中利用更可靠的计时器支持,同时在旧版浏览器上仍能正常运行.
它还允许您避免使用太多的计时器!这很重要:每个计时器都是一个回调.每个回调都执行JS代码.当JS代码正在执行时,浏览器事件(包括其他回调)会被延迟或丢弃.回调完成后,其他回调必须与其他浏览器事件竞争才有机会执行.因此,处理该间隔的所有待处理任务的一个计时器将比具有重合间隔的两个计时器表现更好,并且(对于短暂超时)优于具有重叠超时的两个计时器!
总结:停止使用setTimeout()
实现"一个定时器/一个任务"的设计,并使用实时时钟来平滑UI动作.
.
REF; http://www.sitepoint.com/creating-accurate-timers-in-javascript/
这个网站大规模救了我.
您可以使用系统时钟来补偿定时器的不准确性.如果你将一个计时函数作为一系列setTimeout调用运行 - 每个实例调用下一个 - 那么你要做的就是保持它的准确性,确切地知道它是多么不准确,并从下一次迭代中减去这个差异:
var start = new Date().getTime(), time = 0, elapsed = '0.0'; function instance() { time += 100; elapsed = Math.floor(time / 100) / 10; if(Math.round(elapsed) == elapsed) { elapsed += '.0'; } document.title = elapsed; var diff = (new Date().getTime() - start) - time; window.setTimeout(instance, (100 - diff)); } window.setTimeout(instance, 100);
这种方法可以最大限度地减少漂移,并将不准确度降低90%以上.
它修复了我的问题,希望它有所帮助
我不久前遇到了类似的问题,并提出了一种requestAnimationFrame
与performance.now()相结合的方法,该方法非常有效.
我现在能够将定时器精确到小数点后12位:
window.performance = window.performance || {}; performance.now = (function() { return performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function() { //Doh! Crap browser! return new Date().getTime(); }; })();
http://jsfiddle.net/CGWGreen/9pg9L/