在JavaScript中获取毫秒级时间的更好方法?


141

JavaScript中是否可以使用date对象以毫秒为单位获取时间,或者至少有一种重用该对象的方法,而不必每次需要获取该值时都实例化新对象?我之所以这样问,是因为我试图用JavaScript创建一个简单的游戏引擎,并且在计算“增量帧时间”时,我必须在每个帧中创建一个新的Date对象。尽管我不太担心这种性能的影响,但是我对该对象返回的确切时间的可靠性存在一些问题。

在动画中,我每秒大概会收到一些奇怪的“跳跃”,而且我不确定这是否与JavaScript的Garbage Collection或更新时的Date对象的限制有关。如果我将delta值设置为某个常数,那么动画就可以完美平滑,因此我可以肯定,这种“跳跃”与获取时间的方式有关。

我唯一可以给出的相关代码是计算增量时间的方式:

prevTime = curTime;
curTime = (new Date()).getTime();
deltaTime = curTime - prevTime;

在计算运动/动画时,我将常数值与增量时间相乘。

如果无法避免通过使用Date对象获取以毫秒为单位的时间,则该函数将增加一个变量(即游戏开始以来经过的时间(以毫秒为单位)),然后使用SetTimer函数以每毫秒一次是有效且可靠的替代方法吗?

编辑:我现在已经在不同的浏览器中测试了我的代码,并且似乎“跳”实际上仅在Chrome中可见,而在Firefox中不明显。但是,如果在两种浏览器中都可以使用一种方法,那仍然会很好。


5
每帧一个对象什么都不
CodesInChaos 2012年

2
关于动画每秒跳动,这是否与Date.getMilliseconds当前秒仅返回毫秒(即0到999)有关?您没有在示例中使用此功能,但是可能是在其他地方或其他分支上使用了此功能?
丹·罗斯

2
跳跃与某些奇怪的毫秒分辨率问题有关吗?来自Mozilla的文档:“在使用now()创建时间戳或唯一ID时,请记住,在Windows上,分辨率可能为15毫秒”。可能与打ic有关吗?
zashu

1
@zashu是很久以前的,所以我不记得此示例的任何细节。但是对于最近的应用程序,当使用Date.now()时,我看不到更多跳跃。
Colin Dumitru

Answers:


173

尝试Date.now()

跳过很可能是由于垃圾回收。通常,可以通过尽可能多地重用变量来避免垃圾收集,但是我不能具体说明可以使用哪些方法来减少垃圾收集暂停。


1
我尝试使用Date.now(),但是仍然有相同的跳转。因此,现在我很确定这不是垃圾回收的问题,而是在使用Date对象获取确切值时的限制。就像我说的那样,用恒定值替换增量时间可实现平滑的动画/过渡,因此可能发生的唯一垃圾收集是“ new Date”或“ Date.now()”(如果此函数实例化了自己的对象,我不知道)。
Colin Dumitru'2

22
请注意:在IE8及以下版本中不起作用
Nick

1
我这样做:/我想要的只是以毫秒为单位的日期。对于某些必要的东西似乎是如此复杂。
Damien Golding 2014年

5
@Prozi +1 .. IE真的很烂,当我进行Web编程时,我真的不在乎IE,只是chrome和firefox .....
TechLife 2015年

3
@TechLife您还应该给Android,Safari和Opera浏览器一个思路,但是我同意IE是一大堆垃圾。我的意思是,MS放弃并正在W10中实现新的浏览器非常糟糕
Dendromaniac

49

我知道这是一个非常老的线程,但是为了使事情保持最新并更相关,您可以使用更准确的performance.now()功能来在javascript中获得更精确的计时。

window.performance = window.performance || {};
performance.now = (function() {
    return performance.now       ||
        performance.mozNow    ||
        performance.msNow     ||
        performance.oNow      ||
        performance.webkitNow ||            
        Date.now  /*none found - fallback to browser default */
})();

2
最后一种选择应该只是Date.now代替匿名函数表达式
Bergi 2013年

1
不幸的是,它也不能在笨拙的旧浏览器中使用。幸运的是,我说服我的客户在浪费时间支持IE7和IE8时向我付款。
Michael Scheper

2
|| function(){return new Date()。getTime()}
毫米

2
值得注意的是,它performance.now()提供了单调的时间,这与的时间不同Date。这意味着保证每个后续调用都返回一个不小于前一个值的值。
用户

48

据我所知,您只能在Date上获得时间。

Date.now是解决方案,但并非随处可见:https : //developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/now

var currentTime = +new Date();

这样可以为您提供当前时间(以毫秒为单位)。

为了你的跳跃。如果您根据增量帧时间正确地计算了插值,并且没有四舍五入误差,那么我相信垃圾收集器(GC)。

如果循环中有许多创建的临时对象,则垃圾回收必须锁定线程以进行一些清理和重新组织内存。

使用Chrome,您可以在“ 时间轴”面板中查看GC花费了多少时间。

编辑:自从我的回答以来,Date.now()应被视为最佳选择,因为它在IE> = 9上无处不在。


4
+服务发挥什么作用+new
Andrew Scagnelli 2012年

33
+简单地投DateNumber,给人以毫秒为标准的UNIX时间戳。您可以通过致电(new Date()).getTime()
ngryman '04

9
@mikenelson:对我来说并不可怕,当你知道胁迫的原理时,这很明显Date.now()
ngryman

1
我更喜欢...而+不是.getTime()...它更简单,我不需要记住函数名

2
@TravisJ很棒的快捷方式吗?要检索计算机中已经存在的数值,您可以创建一个对象,调用一个运算符,该运算符测试一个int并触发一个转换,该转换调用一个函数(valueOf),该函数调用类转换方法,该类转换方法最终调用一个函数(getTime)检索值。然后该对象被丢弃,在循环1000次迭代之后,您删除了1000个删除的Date对象,这些对象需要将垃圾收集挂在那里并突然将它们全部丢弃,而当您的计算机滞后时,您想知道发生了什么。:)太棒了!
FrancescoMM

7

如果您有日期对象

var date = new Date('2017/12/03');

然后在javascript中有一个内置方法来获取毫秒格式的日期,即valueOf()

date.valueOf(); //1512239400000 in milliseconds format

2

这是一个非常老的问题-但如果其他人正在看它,仍然可以作为参考- requestAnimationFrame()是在现代浏览器中处理动画的正确方法:

更新:mozilla链接显示了如何执行此操作-我不想重复链接后面的文字;)


4
欢迎使用Stack Overflow!您可能想要简短地说requestAnimationFrame明问题所描述的阻止这种“跳跃”作用的原因。谢谢!
澳洲航空94重型

2
即使使用requestAnimationFrame,我们也不是要假设所有平台上的帧速率都相同,因此我们仍然需要检查当前时间。
汤姆·布泰勒
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.