Лучший способ узнать время в миллисекундах в javascript?

142

Есть ли в JavaScript альтернатива получения времени в миллисекундах с использованием объекта даты или, по крайней мере, способ повторно использовать этот объект без необходимости создавать экземпляр нового объекта каждый раз, когда мне нужно получить это значение? Я спрашиваю об этом, потому что я пытаюсь создать простой игровой движок на JavaScript, и при вычислении «времени дельта-кадра» я должен создавать новый объект Date каждый кадр. Хотя меня не слишком беспокоят последствия этого для производительности, у меня возникают некоторые проблемы с надежностью точного времени, возвращаемого этим объектом.

Я получаю какие-то странные «прыжки» в анимации примерно каждую секунду, и я не уверен, связано ли это со сборкой мусора JavaScript или ограничением объекта Date при таком быстром обновлении. Если я установил значение дельты на некоторую константу, то анимация будет идеально плавной, поэтому я почти уверен, что этот «прыжок» связан с тем, как я получаю время.

Единственный соответствующий код, который я могу дать, - это способ вычисления дельта-времени:

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

При вычислении движения / анимации я умножаю постоянное значение на дельта-время.

Если нет способа избежать получения времени в миллисекундах с помощью объекта Date, будет ли функция, которая увеличивает переменную (которая является истекшим временем в миллисекундах с момента запуска игры) и которая вызывается с использованием функции SetTimer со скоростью раз в миллисекунды быть эффективной и надежной альтернативой?

Изменить: я протестировал свой код в разных браузерах, и кажется, что этот «скачок» действительно заметен только в Chrome, а не в Firefox. Но все равно было бы неплохо, если бы существовал метод, работающий в обоих браузерах.

Колин Думитру
источник
5
Один объект в кадре - ничто
CodesInChaos
3
Что касается анимации, прыгающей каждую секунду, может ли это иметь какое-либо отношение к тому факту, что Date.getMillisecondsв текущей секунде возвращаются только миллисекунды, то есть от 0 до 999? Вы не используете эту функцию в своем примере, но, возможно, она используется где-то еще или в другой ветке?
Дэн Росс
2
Связаны ли прыжки с какими-то странными проблемами разрешения миллисекунд? Из документов Mozilla : «При использовании now () для создания отметок времени или уникальных идентификаторов имейте в виду, что разрешение может составлять 15 миллисекунд в Windows». Может быть, это связано с икотой?
zashu
1
@zashu это было давно, поэтому я не помню подробностей для этого примера. Но для более позднего приложения при использовании Date.now () я больше не вижу прыжков.
Колин Думитру

Ответы:

174

Попробуйте Date.now () .

Пропуск, скорее всего, связан со сборкой мусора. Обычно сборки мусора можно избежать, насколько это возможно, повторным использованием переменных, но я не могу конкретно сказать, какие методы вы можете использовать для уменьшения пауз при сборке мусора.

Йери Себрехтс
источник
1
Я пробовал использовать Date.now (), но у меня все те же прыжки. Итак, теперь я почти уверен, что это не проблема со сборкой мусора, а скорее ограничение при получении точных значений с помощью объекта Date. Как я уже сказал, замена дельта-времени постоянным значением приводит к плавным анимациям / переходам, поэтому единственная сборка мусора, которая может происходить, - это «новая дата» или «Date.now ()» (если эта функция создает собственные объекты, которые Не знаю как).
Колин Думитру
22
Просто предупреждаю: это не работает в IE8 и ниже
Ник
1
Я делаю: / Все, что мне нужно, это дата в мс. Кажется таким сложным для чего-то столь необходимого.
Дэмиен Голдинг
5
@Prozi +1 .. IE действительно отстой, когда я занимаюсь веб-программированием, мне действительно наплевать на IE, только на Chrome и Firefox ..........
TechLife
3
@TechLife Вы также должны подумать о браузерах Android, Safari и Opera, но я согласен, что IE - это полная чушь. Я имею в виду, что это так плохо, что MS
сдалась
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вместо выражения анонимной функции
Берги
1
Также, к сожалению, не работает в старых глупых браузерах. К счастью, я убедил своих клиентов заплатить мне за время, которое я трачу на поддержку IE7 и IE8.
Майкл Шепер
2
|| function () {return new Date (). getTime ()}
ммм
3
Стоит отметить, что время 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 проводит на панели Timeline .

РЕДАКТИРОВАТЬ: Поскольку мой ответ, Date.now()следует рассматривать как лучший вариант, поскольку он поддерживается везде и в IE> = 9.

негритян
источник
4
В какой функции +служит +new?
Эндрю Скагнелли
33
+Просто бросить Dateв Number, давая стандартную метку времени в миллисекундах. Вы можете явно получить это значение, позвонив(new Date()).getTime()
ngryman
9
@mikenelson: Для меня это не страшно, это очевидно, если вы знаете, как работает принуждение. Тем не менее, Date.now()это предпочтительнее сейчас, поскольку его поддержка сейчас достаточно велика.
ngryman 03
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, что останавливает этот "прыжок", как описано в вопросе. Благодарность!
Qantas 94 Heavy
2
Даже с requestAnimationFrame мы не должны предполагать, что частота кадров одинакова на всех платформах, поэтому нам все равно нужно проверять текущее время.
Tom Boutell