JavaScript中的时间戳不一致?

时间:2014-08-27 10:14:48

标签: javascript date timestamp

我在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);

运行几分钟就会给我一个错误:

Chrome DevTools Console Error 1

稍后我会得到另一个,依此类推。

Chrome DevTools Console Error 2

对于此测试,我选择100ms间隔时间来检查许多时间戳。但我的应用程序的更新间隔可能是5秒,但有时仍会出现此错误。不像100毫秒那样频繁,但它就在那里:(

之前有其他人见过这种行为吗?我在这里做错了吗?

BTW:我的应用程序中的数据包逐个进入,因此数据包的顺序不可能混淆或者是......

1 个答案:

答案 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>

这么久......