单调地增加JavaScript中的时间



在JavaScript中获得单调增加的时间的最佳方法是什么?我希望类似Java的System.nanoTime()

Date()显然不能工作,因为它受到系统时间变化的影响。

换句话说,我想要的是对于a <= b, 总是:
a = myIncreasingTime.getMilliseconds();
...
// some time later, maybe seconds, maybe days
b = myIncreasingTime.getMilliseconds();

在最好的情况下,即使在Date()中使用UTC函数,它也会返回它认为正确的时间,但如果有人将时间向后设置,下一次调用Date()可以返回较小的值。System.nanoTime()不受此限制(至少在系统重新启动之前不受此限制)。

修改:[2012-02-26:无意影响原题,有赏金]

我对知道"wall time"不感兴趣,我感兴趣的是知道经过的时间的准确性,这是Date()不可能提供的。

你可以使用windows .performance.now() -自Firefox 15,和windows .performance. webkitnow () - Chrome 20]

var a = window.performance.now();
//...
var delay = window.performance.now() - a;

您可以包装Date()Date.now(),以强制它是单调的(但不准确)。素描,未经测试:

var offset = 0;
var seen = 0;
function time() {
  var t = Date.now();
  if (t < seen) {
    offset += (seen - t);
  }
  seen = t;
  return t + offset;
}

如果将系统时钟设置在给定时刻,则看起来没有时间过去(并且包含该间隔的经过时间将是不正确的),但至少不会出现负增量。如果没有设置,则返回与Date.now()相同的值。

这可能是一个合适的解决方案,如果你正在编写一个游戏模拟循环,例如,time()被频繁调用-最大错误是挫折的次数乘以调用之间的间隔。如果您的应用程序不能自然地做到这一点,您可以显式地在setInterval上调用它(假设系统时钟没有使用它),以牺牲一些CPU时间来保持您的准确性。


也有可能将时钟设置为向前,这并不能防止单调性,但可能会产生同样不良的影响(例如,游戏花费太长时间试图立即赶上其模拟)。然而,这与机器已经休眠了一段时间并没有特别的区别。如果需要这样的保护,它只意味着改变现有条件旁边的条件,为可接受的进度设置一个恒定的阈值:

if (t > seen + leapForwardMaximum) {
  offset += (seen - t) + leapForwardMaximum;
}

我建议leapForwardMaximum应该设置为超过1000毫秒,因为,例如,Chrome(如果我记得正确的话)在背景选项卡中限制计时器每秒不超过一次。

Javascript本身没有任何访问nanoTime的功能。您可以像benchmark.js那样加载java-applet来获取这些信息。也许@mathias可以告诉我们他们在那里做了什么…

Firefox为setTimeout提供了"delay"参数…这是实现单调递增时间计数器的方法之一。

var time = 0;
setTimeout(function x(actualLateness) {
  setTimeout(x, 0);
  time += actualLateness;
}, 0);

最新更新