Javascript milisaniye içinde zaman almak için daha iyi bir yol?


141

JavaScript'te date nesnesini kullanarak milisaniye cinsinden zaman elde etmenin bir alternatifi var mı, yoksa en azından bu değeri almam gerektiğinde yeni bir nesne başlatmak zorunda kalmadan o nesneyi yeniden kullanmanın bir yolu var mı? Bunu soruyorum çünkü JavaScript'te basit bir oyun motoru yapmaya çalışıyorum ve "delta kare zamanını" hesaplarken, her karede yeni bir Date nesnesi oluşturmam gerekiyor. Bunun performans sonuçları hakkında çok endişelenmeme rağmen, bu nesnenin döndürdüğü kesin zamanın güvenilirliği ile ilgili bazı sorunlar yaşıyorum.

Animasyonda her saniyede garip bir "zıplama" alıyorum ve bunun JavaScript'in Çöp Toplama veya bu kadar hızlı güncelleme yaparken Date nesnesinin bir sınırlaması ile ilgili olup olmadığından emin değilim. Delta değerini bazı sabitlere ayarlarsam, o zaman animasyon mükemmel pürüzsüzse, bu yüzden bu "zıplamanın" zamanı alma şeklimizle ilgili olduğundan eminim.

Verebileceğim tek ilgili kod, delta zamanını hesaplama şeklimdir:

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

Hareket / animasyon hesaplanırken sabit bir değeri delta zamanı ile çarpıyorum.

Date nesnesini kullanarak milisaniye cinsinden zamanı elde etmekten kaçınmanın bir yolu yoksa, bir değişkeni artıran (oyun başladığından bu yana geçen milisaniye cinsinden geçen süre olan) ve SetTimer işlevi kullanılarak her milisaniyede bir verimli ve güvenilir bir alternatif olabilir mi?

Düzenleme: Şimdi kodumu farklı tarayıcılarda test ettim ve bu "atlama" gerçekten sadece Chrome'da görünür, Firefox'ta değil gibi görünüyor. Ancak, her iki tarayıcıda da çalışan bir yöntem olsaydı yine de iyi olurdu.


5
Çerçeve başına bir nesne hiçbir şey değildir
CodesInChaos

2
Her saniye atlayan animasyon hakkında, bunun Date.getMillisecondssadece geçerli saniyedeki milisaniyeyi (yani 0 - 999) döndüren bir şey olabilir mi? Örneğinizde bu işlevi kullanmıyorsunuz, ama belki başka bir yerde mi yoksa farklı bir dalda mı kullanılıyor?
Dan Ross

2
Atlama, bazı garip milisaniye çözünürlük sorunlarıyla mı ilgili? Gönderen Mozilla docs : "() zaman damgalarını veya benzersiz kimlikler yaratmak için şimdi kullanırken, çözünürlük Windows üzerinde 15 milisaniye olabileceğini akılda tutmak". Bu hıçkırıklarla ilgili olabilir mi?
Mart'ta Zashu

1
@zashu bu çok uzun zaman önceydi, bu yüzden bu örnek için hiçbir ayrıntı hatırlamıyorum. Ancak daha yeni bir uygulama için, Date.now () kullanırken artık atlama görmüyorum.
Colin Dumitru

Yanıtlar:


173

Date.now () yöntemini deneyin .

Atlama büyük olasılıkla çöp toplama işleminden kaynaklanmaktadır. Genellikle çöp toplama, değişkenleri mümkün olduğunca yeniden kullanarak önlenebilir, ancak çöp toplama duraklamalarını azaltmak için hangi yöntemleri kullanabileceğinizi özellikle söyleyemem.


1
Date.now () kullanmayı denedim, ama yine de aynı sıçramalar var. Şimdi çöp toplama ile ilgili bir sorun değil, Date nesnesi ile kesin değerler alırken bir sınırlama olduğundan eminim. Dediğim gibi, delta zamanını sabit bir değerle değiştirmek yumuşak animasyonlar / geçişler ile sonuçlanır, bu yüzden olabilecek tek çöp toplama "yeni Tarih" veya "Date.now ()" ile olur (eğer bu fonksiyon kendi nesnelerini başlatırsa Bilmiyorum).
Colin Dumitru

22
Sadece bir kafa yukarı: Bu IE8 ve altında çalışmıyor
Nick

1
Yapıyorum: / İstediğim tek şey ms cinsinden tarih. Bu kadar gerekli bir şey için çok karmaşık görünüyor.
Damien Golding

5
@Prozi +1 .. IE gerçekten berbat, Im web programlama Ben gerçekten IE, sadece krom ve firefox umurumda değil ..........
TechLife

3
@TechLife Ayrıca Android, Safari ve opera tarayıcılarına bir düşünce dizisi vermelisiniz, ancak IE'nin bir yük çöp olduğunu kabul ediyorum. Yani MS'in
W10'da

49

Bunun oldukça eski bir iş parçacığı olduğunu biliyorum, ancak işleri güncel tutmak ve daha alakalı performance.now()olmak için, javascript'te daha iyi tahıl zamanlaması elde etmek için daha doğru işlevselliği kullanabilirsiniz.

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
Son alternatif, Date.nowanonim bir işlev ifadesi yerine olmalıdır
Bergi

1
Ne yazık ki aptal eski tarayıcılarda da çalışmıyor. Neyse ki, müşterilerimi IE7 ve IE8'i desteklediğim için bana ödeme yapmaya ikna ettim.
Michael Scheper

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

2
Bu performance.now()zamanın aksine, monoton zaman verir Date. Bu, sonraki her çağrının bir öncekinden daha az olmayan bir değer döndüreceği garanti edilir.
kullanıcı

48

Bildiğim kadarıyla sadece Date ile zaman alabilirsin .

Date.now bir çözümdür ancak her yerde mevcut değildir: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/now .

var currentTime = +new Date();

Bu size milisaniye cinsinden geçerli saati verir.

Sizin için atlamaları . İnterpolasyonları delta kare zamanına göre doğru hesaplarsanız ve yuvarlama numarası hatası yoksa , çöp toplayıcı (GC) için bahse girerim.

Döngünüzde çok sayıda oluşturulmuş geçici nesne varsa, çöp toplama işlemi bir miktar temizleme ve bellek yeniden düzenleme yapmak için iş parçacığını kilitlemek zorundadır.

Chrome ile GC'nin Zaman Çizelgesi panelinde ne kadar zaman harcadığını görebilirsiniz .

EDIT: Cevabım beri, Date.now()her yerde ve IE> = 9 desteklendiği için en iyi seçenek olarak kabul edilmelidir.


4
Ne fonksiyonu yok +hizmet +new?
Andrew Scagnelli

33
+Basitçe döküm Dateiçin Numbermilisaniye cinsinden bir standart unix zaman damgası vererek. Bu değeri açıkça arayarak alabilirsiniz(new Date()).getTime()
ngryman

9
@mikenelson: Benim için korkunç değil, zorlamanın nasıl çalıştığını bildiğinizde bu açıktır Date.now().
ngryman

1
Sadece tercih +daha .getTime()... Daha basit ve ben fonksiyon isimleri ezberlemek gerek yok

2
@TravisJ Harika kısayol? Zaten bilgisayarınızın içinde bulunan sayısal bir değeri almak için bir nesne oluşturursunuz, bir int için test yapan ve sonunda bir işlevi (getTime) çağıran bir işlevi (getTime) çağıran sınıf dönüştürme yöntemini çağıran bir işlevi (valueOf) çağıran bir dönüşümü tetikleyen bir işleci arayın. değeri alır. Sonra nesne kaderine terk edilir ve 1000 döngü yinelemesinden sonra, aniden bir araya toplanan çöp toplama gerektiren 1000 silinmiş Date nesnesine sahip olursunuz ve bilgisayarınız geride kaldığında ne olduğunu merak edersiniz. :) Harika!
FrancescoMM

7

Gibi bir tarih nesneniz varsa

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

daha sonra milisaniye formatında tarihini almak için javascript dahili yöntem yoktur valueOf ()

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

2

Bu çok eski bir soru - ama yine de başkaları bakıyorsa referans için - requestAnimationFrame()modern tarayıcılarda animasyonla başa çıkmanın doğru yolu:

GÜNCELLEME: Mozilla bağlantısı bunun nasıl yapılacağını gösterir - Bağlantının arkasındaki metni tekrarlamak gibi hissetmedim;)


4
Stack Overflow'a hoş geldiniz ! requestAnimationFrameSoruda açıklandığı gibi bu "zıplamayı" neyin durdurduğuna dair kısa bir açıklama eklemek isteyebilirsiniz . Teşekkürler!
Qantas 94 Heavy

2
RequestAnimationFrame ile bile, kare hızının tüm platformlarda aynı olduğunu varsaymak istemiyoruz, bu yüzden şimdiki zamanı kontrol etmemiz gerekiyor.
Tom Boutell
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.