12

浏览器已经回答了这个问题here,但window.performance.now()显然在 Node.js 中不可用。

一些应用需要稳定的时钟,即随时间单调增加的时钟,不受系统时钟漂移的影响。例如,Java 有System.nanoTime(),C++ 有std::chrono::steady_clock. Node.js 中有这样的时钟吗?

4

2 回答 2

18

原来 Node.js 中的等价物是process.hrtime(). 根据文档:

[从 process.hrtime() 返回的时间] 相对于过去的任意时间,与一天中的时间无关,因此不受时钟漂移的影响。


例子

假设我们希望每秒定期调用某个 REST 端点,处理其结果并将某些内容打印到日志文件中。考虑端点可能需要一段时间来响应,例如,从数百毫秒到超过一秒。我们不希望有两个并发请求,所以setInterval()不能完全满足我们的需求。

一种好的方法是第一次调用我们的函数,执行请求,处理它,然后调用setTimeout()并重新安排另一个运行。但考虑到我们发出请求所花费的时间,我们希望每秒执行一次。这是使用我们稳定时钟的一种方法(这将保证我们不会被系统时钟漂移所迷惑):

function time() {
    const nanos = process.hrtime.bigint();
    return Number(nanos / 1_000_000n);
}

async function run() {
    const startTime = time();

    const response = await doRequest();
    await processResponse(response);

    const endTime = time();
    // wait just the right amount of time so we run once second; 
    // if we took more than one second, run again immediately
    const nextRunInMillis = Math.max(0, 1000 - (endTime - startTime));
    setTimeout(run, nextRunInMillis);
}

run();

我制作了这个辅助函数time(),它将返回的值转换为process.hrtime.bigint()毫秒分辨率的时间戳;这个应用程序的分辨率足够了。

于 2017-10-26T22:26:03.253 回答
2

添加了 NodeJS 10.7.0 process.hrtime.bigint()

然后你可以这样做:


function monotimeRef() {
  return process.hrtime.bigint();
}

function monotimeDiff(ref) {
  return Number(process.hrtime.bigint() - ref) / 10**9;
}

演示 Node REPL 中的用法:

// Measure reference time.
> let t0 = monotimeRef();
undefined

[ ... let some time pass ... ]

// Measure time passed since reference time,
// in seconds.
> monotimeDiff(t0)
12.546663115

笔记:

  • Number()将 a 转换BigInt为常规Number类型,允许使用普通除法运算符将纳秒转换为秒。
  • monotimeDiff()返回以纳秒分辨率传递的壁时间差作为浮点数(在进行除法Number 之前转换为)。
  • 这假设测量的持续时间不会超过 2^53 ns,实际上只是大约 104 天 ( 2**53 ns / 10**9 ns/s / 86400.0 s/day = 104.3 day)。
于 2019-11-20T02:27:04.777 回答