Cara yang lebih baik untuk mendapatkan waktu dalam milidetik dalam javascript?

141

Apakah ada alternatif dalam JavaScript untuk mendapatkan waktu dalam milidetik menggunakan objek tanggal, atau setidaknya cara untuk menggunakan kembali objek itu, tanpa harus membuat instance objek baru setiap kali saya perlu mendapatkan nilai ini? Saya menanyakan ini karena saya mencoba membuat mesin gim sederhana dalam JavaScript, dan ketika menghitung "delta frame time", saya harus membuat objek Date baru setiap frame. Meskipun saya tidak terlalu khawatir tentang implikasi kinerja ini, saya mengalami beberapa masalah dengan keandalan waktu yang tepat dikembalikan oleh objek ini.

Saya mendapatkan "lompatan" aneh dalam animasi, setiap detik atau lebih, dan saya tidak yakin apakah ini terkait dengan JavaScript's Garbage Collection atau batasan objek Date saat memperbarui dengan sangat cepat. Jika saya mengatur nilai delta ke beberapa konstanta, maka animasi jika mulus, jadi saya cukup yakin ini "melompat" terkait dengan cara saya mendapatkan waktu.

Satu-satunya kode yang relevan yang dapat saya berikan adalah cara saya menghitung waktu delta:

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

Saat menghitung pergerakan / animasi saya mengalikan nilai konstan dengan waktu delta.

Jika tidak ada cara untuk menghindari mendapatkan waktu dalam milidetik dengan menggunakan objek Date, akankah fungsi yang menambah variabel (menjadi waktu yang berlalu dalam milidetik sejak permainan dimulai), dan yang disebut menggunakan fungsi SetTimer pada tingkat sekali setiap milidetik menjadi alternatif yang efisien dan andal?

Sunting: Saya telah menguji sekarang kode saya di browser yang berbeda dan tampaknya "lompatan" ini benar-benar hanya terlihat di Chrome, bukan di Firefox. Tapi alangkah baiknya jika ada metode yang bisa digunakan di kedua browser.

Colin Dumitru
sumber
5
Satu objek per bingkai bukanlah apa
CodesInChaos
2
Tentang lompatan animasi setiap detik, dapatkah ini ada hubungannya dengan fakta bahwa Date.getMillisecondshanya mengembalikan milidetik dalam detik saat ini, yaitu 0 hingga 999? Anda tidak menggunakan fungsi ini dalam contoh Anda, tetapi mungkin sedang digunakan di tempat lain, atau pada cabang yang berbeda?
Dan Ross
2
Apakah lompatan terkait dengan beberapa masalah resolusi milidetik aneh? Dari dokumen Mozilla : "Saat menggunakan now () untuk membuat cap waktu atau ID unik, ingatlah bahwa resolusinya mungkin 15 milidetik di Windows". Mungkinkah itu terkait dengan cegukan?
zashu
1
@ zashu ini sudah lama sekali, jadi saya tidak ingat spesifik untuk contoh ini. Tetapi untuk aplikasi yang lebih baru, ketika menggunakan Date.now () saya tidak melihat lagi melompat.
Colin Dumitru

Jawaban:

173

Coba Date.now () .

Melompati kemungkinan besar karena pengumpulan sampah. Biasanya pengumpulan sampah dapat dihindari dengan menggunakan kembali variabel sebanyak mungkin, tetapi saya tidak bisa mengatakan secara spesifik metode apa yang dapat Anda gunakan untuk mengurangi pengumpulan sampah yang dihentikan.

Joeri Sebrechts
sumber
1
Saya telah mencoba menggunakan Date.now (), tetapi saya masih memiliki lompatan yang sama. Jadi sekarang saya cukup yakin bahwa itu bukan masalah dengan pengumpulan sampah, melainkan batasan ketika mendapatkan nilai yang tepat dengan objek Date. Seperti yang saya katakan, mengganti waktu delta dengan nilai konstan menghasilkan animasi / transisi yang lancar, jadi satu-satunya pengumpulan sampah yang mungkin terjadi adalah dengan "Date baru" atau "Date.now ()" (jika fungsi ini instantiates objek itu sendiri yang Saya tidak tahu tentang).
Colin Dumitru
22
Hanya kepala: Ini tidak bekerja di IE8 dan di bawah ini
Nick
1
Saya lakukan: / Yang saya inginkan adalah tanggal dalam ms. Tampaknya sangat rumit untuk sesuatu yang sangat perlu.
Damien Golding
5
@Prozi +1 .. IE benar-benar menyebalkan, ketika saya pemrograman web saya benar-benar tidak peduli tentang IE, hanya chrome dan firefox ..........
TechLife
3
@ TechLife Anda juga harus mempertimbangkan browser Android, Safari, dan opera, tapi saya setuju IE adalah banyak sampah. Maksud saya, sangat buruk bahwa MS telah menyerah dan mengimplementasikan browser baru di W10
Dendromaniac
49

Saya tahu ini adalah utas yang cukup lama, tetapi untuk tetap mengikuti perkembangan dan lebih relevan, Anda dapat menggunakan performance.now()fungsionalitas yang lebih akurat untuk mendapatkan penentuan waktu butir yang lebih baik dalam 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 */
})();
Chris GW Green
sumber
2
Alternatif terakhir seharusnya hanya Date.nowalih-alih ekspresi fungsi anonim
Bergi
1
Sayangnya, juga tidak berfungsi di browser lama yang bodoh. Untungnya, saya sudah meyakinkan klien saya untuk membayar saya untuk waktu yang saya buang mendukung IE7 dan IE8.
Michael Scheper
2
|| function () {return Date baru (). getTime ()}
mmm
2
Perlu dicatat bahwa performance.now()memberi waktu monoton, tidak seperti waktu dari Date. Ini berarti bahwa setiap panggilan berikutnya dijamin untuk mengembalikan nilai tidak kurang dari yang sebelumnya.
pengguna
48

Sejauh yang saya tahu Anda hanya bisa mendapatkan waktu dengan Date .

Date.now adalah solusinya tetapi tidak tersedia di mana-mana: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/now .

var currentTime = +new Date();

Ini memberi Anda waktu saat ini dalam milidetik.

Untuk lompatanmu . Jika Anda menghitung interpolasi dengan benar sesuai dengan waktu bingkai delta dan Anda tidak memiliki kesalahan angka pembulatan , saya bertaruh untuk pengumpul sampah (GC).

Jika ada banyak objek sementara yang dibuat di loop Anda, pengumpulan sampah harus mengunci utas untuk melakukan pembersihan dan pengaturan ulang memori.

Dengan Chrome Anda dapat melihat berapa banyak waktu yang dihabiskan GC di panel Timeline .

EDIT: Karena jawaban saya, Date.now()harus dianggap sebagai opsi terbaik karena didukung di mana-mana dan di IE> = 9.

orang Inggris
sumber
4
Fungsi apa yang +dilayaninya +new?
Andrew Scagnelli
33
The +hanya melemparkan Dateke Number, memberikan cap waktu unix standar dalam milidetik. Anda dapat secara eksplisit mendapatkan nilai ini dengan menelepon(new Date()).getTime()
ngryman
9
@mikenelson: Tidak buruk bagi saya, ini jelas ketika Anda tahu cara kerja paksaan. Yang mengatakan, Date.now()lebih disukai sekarang karena dukungannya cukup besar sekarang.
ngryman
1
Saya lebih suka +daripada .getTime()... Ini lebih sederhana dan saya tidak perlu menghafal nama
2
@ TravisJ Pintasan mengagumkan? Untuk mengambil nilai numerik yang sudah ada di dalam komputer Anda, Anda membuat objek, memanggil operator yang menguji int dan memicu konversi yang memanggil fungsi (valueOf) yang memanggil metode konversi kelas yang memanggil fungsi (getTime) yang akhirnya mengambil nilai. Kemudian objek ditinggalkan ke takdirnya, dan setelah 1000 iterasi dari loop Anda telah menghapus 1000 objek Date yang membutuhkan pengumpulan sampah tergantung di sana yang tiba-tiba dibuang bersama-sama, dan ketika komputer Anda tertinggal Anda bertanya-tanya apa yang terjadi. :) Luar biasa!
FrancescoMM
7

Jika Anda memiliki objek kencan suka

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

kemudian ada metode inbuilt di javascript untuk mendapatkan tanggal dalam format milidetik yang bernilaiOf ()

date.valueOf(); //1512239400000 in milliseconds format
dilip kumar
sumber
2

Ini adalah pertanyaan yang sangat lama - tetapi masih untuk referensi jika orang lain melihatnya - requestAnimationFrame()adalah cara yang tepat untuk menangani animasi di browser modern:

UPDATE: Tautan mozilla menunjukkan cara melakukan ini - saya tidak ingin mengulangi teks di balik tautan;)

LarsKnudsen
sumber
4
Selamat Datang di Stack Overflow ! Anda mungkin ingin memasukkan penjelasan singkat tentang apa requestAnimationFrameyang menghentikan "lompatan" ini seperti yang dijelaskan dalam pertanyaan. Terima kasih!
Qantas 94 Heavy
2
Bahkan dengan requestAnimationFrame, kami tidak dimaksudkan untuk menganggap frame rate sama pada semua platform, jadi kami masih perlu memeriksa waktu saat ini.
Tom Boutell