我在JS中使用Date.now()函数遇到了一些奇怪的错误。
背景信息:我正在开发一个webApp,用于向/从服务器发送和接收数据包。我的所有传入数据包都标有时间戳,由Date.now()生成。这些数据包中的数据是打印在折线图中的数据。所以我在y轴上得到一个值,在x轴上得到时间戳。到目前为止一切都很好。
让app运行给我一些奇怪的行为 - >我的折线图有时会在已经存在的数据点之前回溯过去的数据点!在检查我看到的这些点的时间戳时,我的图表做的一切正确,但时间戳是错误的。
所以我写了一个小测试脚本,以收集更多证据:
var i = 0;
var ts = [Date.now()];
setInterval(function () {
ts.push(Date.now());
console.info("checking next timestamp ...");
if (ts[i] > ts[i+1]) {
console.error("old timestamp (" + ts[i] + ") is BIGGER than current timestamp (" + ts[i+1] + ")!");
}
i++;
}, 100);
运行几分钟就会给我一个错误:
稍后我会得到另一个,依此类推。
对于此测试,我选择100ms间隔时间来检查许多时间戳。但我的应用程序的更新间隔可能是5秒,但有时仍会出现此错误。不像100毫秒那样频繁,但它就在那里:(
之前有其他人见过这种行为吗?我在这里做错了吗?
BTW:我的应用程序中的数据包逐个进入,因此数据包的顺序不可能混淆或者是......
答案 0 :(得分:0)
好吧,我昨天看了一下Performance API,我认为这是要走的路。我在我的应用程序中实现了它,如下所示:
每当我从服务器收到输入数据包时,我都会给他们一个时间戳。到目前为止,我已经通过Date.now()实现了这一点,但这似乎是不一致的,因为操作系统或VM(或两者)不时重新计算当前时间。
所以现在我计算自己的时间戳。为此,我必须从应用程序启动时读取时间戳。性能API通过
为我提供了这个值var startTS = window.performance.timing.navigationStart; //returns a timestamp in ms
因此,这是我的应用程序中随处可用的值,因为它存在于窗口命名空间中,并且不需要我自己创建的全局变量。很好。
现在,要获取当前时间戳,我必须添加一个时间值,指示自startTS以来我的应用程序运行了多长时间。为此,我们只使用:
var timeSinceStartup = window.performance.now(); //returns sth. like 1337.9836718 (ms with fractional part)
如果需要,可以对此值进行舍入,因为可能不需要小数部分:
var rounded = (timeSinceStartup + 0.5) | 0; //same as but faster than Math.round(timeSinceStartup);
嗯,其余的很容易。我们只需添加这些值(两者都是毫秒)和瞧:
var currentTS = startTS + timeSinceStartup;
我已经更新了我的问题中的小代码片段来测试它:
var i = 0;
var start = window.performance.timing.navigationStart;
var ts = [start + window.performance.now()];
setInterval(function () {
ts.push(start + window.performance.now());
console.info("checking next timestamp ...");
if (ts[i] > ts[i+1]) {
console.error("old timestamp (" + ts[i] + ") is BIGGER than current timestamp (" + ts[i+1] + ")!");
}
i++;
}, 100);
Chrome目前正在运行此测试(在VM中),看起来一切都很好(17500次检查没有错误)。我想知道是不是......否则会发生,因为我们只是添加一个具有单调上升值的常量;)
此解决方案的唯一缺点似乎是浏览器支持。截至目前,每个现代浏览器都支持Safari。由于我的应用程序开发只能在现代浏览器上运行,这对我来说没问题,但缺少Safari是不好的。
http://caniuse.com/#feat=high-resolution-time
我将不得不看看crossbrowser解决方案/ polyfills / Frameworks或者......谢谢大家的帮助。无论如何,我仍然很好奇Chrome中是否有Date.now()的解决方案,因为FF和IE在使用它时没有任何问题。
https://code.google.com/p/chromium/issues/detail?id=408077
修改的
对于缺少的Performance API,这似乎是一个很好的polyfill: https://gist.github.com/paulirish/5438650
当然它会回溯到Date.now(),因此在不支持API的浏览器中,我可能遇到与以前相同的问题。对于这种情况,我只是继续检查应用程序中的时间戳,如果发生计时错误,我将默默地处理它(例如,不要将其绘制到图表中,而是等待下一个值)。 / p>
这么久......