Кращий спосіб отримати час у мілісекундах у JavaScript?


141

Чи є альтернатива в JavaScript отримати час у мілісекундах за допомогою об’єкта дати чи принаймні спосіб повторно використовувати цей об’єкт, не потребуючи інстанціювання нового об'єкта щоразу, коли мені потрібно отримати це значення? Я запитую це, тому що я намагаюся зробити простий ігровий механізм в JavaScript, і при обчисленні "часу дельта-кадру" я повинен створювати новий об'єкт дати кожен кадр. Хоча я не надто переживаю наслідки цього для продуктивності, у мене виникають деякі проблеми з надійністю точного часу, поверненого цим об'єктом.

Я отримую якісь дивні "стрибки" в анімації, щосекунди або близько того, і я не впевнений, що це пов'язано зі збиранням сміття JavaScript або обмеженням об'єкта Date, коли так швидко оновлюється. Якщо я встановити значення дельта на деяку константу, то анімація, якщо ідеально гладка, тож я впевнений, що це "стрибки" пов'язане з тим, як я отримую час.

Єдиний відповідний код, який я можу дати, - це спосіб обчислення часу дельти:

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

При обчисленні руху / анімації я множу постійне значення на дельта-час.

Якщо немає можливості уникнути отримання часу в мілісекундах за допомогою об’єкта Date, буде функція, що збільшує змінну (що минув час у мілісекундах з моменту початку гри), і яка викликається за допомогою функції SetTimer зі швидкістю раз на мілісекунди бути ефективною та надійною альтернативою?

Редагувати: я перевірив свій код у різних браузерах і, схоже, цей «стрибок» дійсно очевидний лише у Chrome, а не у Firefox. Але все одно було б добре, якби був метод, який працював в обох браузерах.


5
Один об’єкт на кадр - це нічого
CodesInChaos

2
Щодо того, що анімація стрибає щосекунди, чи може це мати щось спільне з тим, що Date.getMillisecondsповертає лише мілісекунди в поточну секунду, тобто 0 до 999? Ви не використовуєте цю функцію у своєму прикладі, але, можливо, вона використовується десь в іншому місці чи в іншій гілці?
Ден Росс

2
Чи пов’язані стрибки з якимись дивними проблемами вирішення мільйонних секунд? З документів Mozilla : "Використовуючи now () для створення часових міток або унікальних ідентифікаторів, майте на увазі, що роздільна здатність може бути 15 мілісекунд у Windows". Це може бути пов’язано з гикавкою?
зашу

1
@zashu це було давно, тому я не пам’ятаю жодної конкретики для цього прикладу. Але для більш пізнього застосування, коли використовую Date.now (), я більше не бачу стрибків.
Колін Думітру

Відповіді:


173

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

Пропуск, швидше за все, пов’язаний зі збиранням сміття. Зазвичай збирання сміття можна уникнути, використовуючи змінні якомога більше, але я не можу конкретно сказати, які методи ви можете використовувати, щоб зменшити паузи з вивезенням сміття.


1
Я спробував використовувати Date.now (), але у мене все одно такі ж стрибки. Тож зараз я впевнений, що це не проблема зі збиранням сміття, а скоріше обмеження при отриманні точних значень об’єкта Date. Як я вже говорив, заміна дельта-часу постійним значенням призводить до плавних анімацій / переходів, тому єдиний збір сміття, який може статися, - це "new Date" або "Date.now ()" (якщо ця функція створює власні об'єкти, які Я не знаю про це).
Колін Думітру

22
Лише вгору: Це не працює в IE8 і нижче
Нік

1
Я роблю: / Все, що я хочу, це дата в мс. Здається так складно для чогось такого необхідного.
Демієн Голдінг

5
@Prozi +1 .. IE дійсно смокче, коли в Інтернеті програмування мене дуже не хвилює IE, просто хром і firefox ..........
TechLife

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замість анонімного вираження функції
Бергі

1
На жаль, також не працює у дурних старих браузерах. На щастя, я переконав своїх клієнтів платити мені за час, який я витрачаю на підтримку IE7 та IE8.
Майкл Шепер

2
|| function () {return new Date (). getTime ()}
mmm

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 на панелі Timeline .

EDIT: Оскільки моя відповідь, Date.now()слід вважати найкращим варіантом, оскільки вона підтримується скрізь і в IE> = 9.


4
Яку функцію виконує +подача +new?
Ендрю Скагнеллі

33
+Просто кинути Dateв Number, даючи стандартну мітку часу в мілісекундах. Ви можете отримати це значення явно за телефоном(new Date()).getTime()
ngryman

9
@mikenelson: Для мене не страшно, це очевидно, коли ви знаєте, як працює примус. Тим не менш, Date.now()зараз його віддають перевагу, оскільки його підтримка зараз досить велика.
ngryman

1
Я вважаю за краще просто , +ніж .getTime()... Це простіше і не потрібно запам'ятовувати імена функцій

2
Яскравий ярлик @TravisJ? Щоб отримати числове значення, яке вже є у вашому комп'ютері, ви створюєте об'єкт, зателефонуйте оператору, який тестує на int та запустить перетворення, яке викликає функцію (valueOf), яка викликає метод перетворення класу, який викликає функцію (getTime), що нарешті отримує значення. Тоді об’єкт кидається до своєї долі, і після 1000 ітерацій циклу у вас є 1000 видалених об'єктів, що вимагають вивезення сміття, які висять там, і раптом їх збирають разом, і поки ваш комп'ютер відстає, вам цікаво, що відбувається. :) Дивовижно!
FrancescoMM

7

Якщо у вас є такий об'єкт дати

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

тоді є вбудований метод у javascript для отримання дати у форматі мілісекунд, який є valueOf ()

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

2

Це дуже старе питання - але все ж для довідок, якщо інші дивляться на нього - requestAnimationFrame()це правильний спосіб роботи з анімацією в сучасних браузерах:

ОНОВЛЕННЯ: Посилання mozilla показує, як це зробити - мені не здалося повторювати текст за посиланням;)


4
Ласкаво просимо до переповнення стека ! Ви можете включити коротке пояснення того, що requestAnimationFrameробить це, що зупиняє це "стрибки", як описано в питанні. Дякую!
Qantas 94 Важкий

2
Навіть із requestAnimationFrame ми не маємо на увазі вважати, що частота кадрів однакова на всіх платформах, тому нам ще потрібно перевірити поточний час.
Том Бутел
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.