浏览器已经回答了这个问题here,但window.performance.now()
显然在 Node.js 中不可用。
一些应用需要稳定的时钟,即随时间单调增加的时钟,不受系统时钟漂移的影响。例如,Java 有System.nanoTime()
,C++ 有std::chrono::steady_clock
. Node.js 中有这样的时钟吗?
浏览器已经回答了这个问题here,但window.performance.now()
显然在 Node.js 中不可用。
一些应用需要稳定的时钟,即随时间单调增加的时钟,不受系统时钟漂移的影响。例如,Java 有System.nanoTime()
,C++ 有std::chrono::steady_clock
. Node.js 中有这样的时钟吗?
原来 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()
毫秒分辨率的时间戳;这个应用程序的分辨率足够了。
添加了 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
)。