วิธีที่ดีกว่าในการรับเวลาเป็นมิลลิวินาทีใน javascript หรือไม่


141

มีทางเลือกอื่นใน JavaScript ในการรับเวลาเป็นมิลลิวินาทีโดยใช้อ็อบเจกต์ Date หรืออย่างน้อยก็เป็นวิธีนำวัตถุนั้นกลับมาใช้ใหม่โดยไม่ต้องสร้างอินสแตนซ์ของวัตถุใหม่ทุกครั้งที่ต้องการรับค่านี้ ฉันถามสิ่งนี้เพราะฉันกำลังพยายามสร้างเอ็นจิ้นเกมอย่างง่ายใน JavaScript และเมื่อคำนวณ "เวลาของเดลต้าเฟรม" ฉันต้องสร้างวัตถุวันที่ใหม่ทุกเฟรม ในขณะที่ฉันไม่ได้กังวลเกี่ยวกับผลกระทบของประสิทธิภาพการทำงานนี้ฉันมีปัญหากับความน่าเชื่อถือของเวลาที่แน่นอนที่ส่งคืนโดยวัตถุนี้

ฉันได้รับ "กระโดด" แปลกในภาพเคลื่อนไหวทุกวินาทีหรือมากกว่านั้นและฉันไม่แน่ใจว่าเกี่ยวข้องกับ Garbage Collection หรือข้อ จำกัด ของวัตถุ Date เมื่ออัปเดตเร็วเกินไป ถ้าฉันตั้งค่าเดลต้าเป็นค่าคงที่ดังนั้นอนิเมชั่นก็ราบรื่นดีดังนั้นฉันค่อนข้างแน่ใจว่า "การกระโดด" นี้เกี่ยวข้องกับวิธีที่ฉันได้รับเวลา

รหัสที่เกี่ยวข้องเท่านั้นที่ฉันสามารถให้ได้คือวิธีที่ฉันคำนวณเวลาเดลต้า:

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

เมื่อคำนวณการเคลื่อนไหว / แอนิเมชันฉันจะคูณค่าคงที่กับเวลาของเดลต้า

หากไม่มีวิธีหลีกเลี่ยงการรับเวลาเป็นมิลลิวินาทีโดยใช้วัตถุวันที่จะมีฟังก์ชั่นที่เพิ่มตัวแปร (เป็นเวลาที่ผ่านไปเป็นมิลลิวินาทีนับตั้งแต่เริ่มเกม) และเรียกใช้ฟังก์ชัน SetTimer ในอัตรา ทุกหนึ่งมิลลิวินาทีเป็นทางเลือกที่มีประสิทธิภาพและเชื่อถือได้หรือไม่

แก้ไข: ฉันได้ทดสอบแล้วตอนนี้รหัสของฉันในเบราว์เซอร์ที่แตกต่างกันและดูเหมือนว่า "ข้าม" นี้จะปรากฏใน Chrome เท่านั้นไม่ใช่ใน Firefox แต่มันจะยังดีถ้ามีวิธีที่ใช้ได้กับเบราว์เซอร์ทั้งสอง


5
วัตถุหนึ่งชิ้นต่อเฟรมคือไม่มีอะไร
CodesInChaos

2
เกี่ยวกับอนิเมชั่นที่กระโดดทุก ๆ วินาทีสิ่งนี้จะเกี่ยวข้องกับข้อเท็จจริงที่Date.getMillisecondsส่งกลับเฉพาะมิลลิวินาทีในวินาทีปัจจุบันคือ 0 ถึง 999 หรือไม่ คุณไม่ได้ใช้ฟังก์ชั่นนี้ในตัวอย่างของคุณ แต่บางทีมันอาจจะถูกใช้ที่อื่นหรือในสาขาอื่น?
Dan Ross

2
การกระโดดเกี่ยวข้องกับปัญหาการแก้ปัญหาบางมิลลิวินาทีแปลกหรือไม่ จากMozilla docs : "เมื่อใช้ตอนนี้ () เพื่อสร้างการประทับเวลาหรือรหัสที่ไม่ซ้ำโปรดทราบว่าการแก้ไขอาจใช้เวลา 15 มิลลิวินาทีใน Windows" นั่นอาจเกี่ยวข้องกับการสะอึก?
zashu

1
@zashu นี่นานมาแล้วดังนั้นฉันจำไม่ได้ว่าเฉพาะตัวอย่างนี้ แต่สำหรับแอพพลิเคชั่นล่าสุดเมื่อใช้ Date.now () ฉันไม่เห็นการกระโดดอีกแล้ว
โคลิน Dumitru

คำตอบ:


173

ลองDate.now ()

การกระโดดข้ามน่าจะเกิดจากการเก็บขยะ โดยทั่วไปแล้วการเก็บขยะสามารถหลีกเลี่ยงได้โดยการใช้ตัวแปรซ้ำให้มากที่สุด แต่ฉันไม่สามารถพูดได้อย่างชัดเจนว่าวิธีการใดที่คุณสามารถใช้เพื่อลดการหยุดเก็บขยะชั่วคราว


1
ฉันได้ลองใช้ Date.now () แต่ฉันยังคงมีการข้ามที่เหมือนกัน ดังนั้นตอนนี้ฉันค่อนข้างมั่นใจว่ามันไม่ได้มีปัญหากับการเก็บขยะ แต่ค่อนข้าง จำกัด เมื่อได้รับค่าที่แน่นอนด้วยวัตถุวันที่ อย่างที่ฉันพูดการแทนที่เวลาเดลต้าด้วยค่าคงที่ส่งผลให้เกิดภาพเคลื่อนไหว / การเปลี่ยนภาพที่ราบรื่นดังนั้นการรวบรวมขยะเพียงอย่างเดียวที่อาจเกิดขึ้นก็คือ "วันที่ใหม่" หรือ "Date.now ()" (หากฟังก์ชันนี้สร้างวัตถุของตัวเอง ฉันไม่รู้)
โคลิน Dumitru

22
แค่หัวขึ้น: มันไม่ทำงานใน IE8 และด้านล่าง
นิค

1
ฉัน: / ทั้งหมดที่ฉันต้องการคือวันที่ในหน่วยมิลลิวินาที ดูเหมือนจะซับซ้อนสำหรับบางสิ่งที่จำเป็น
Damien Golding

5
@Prozi +1 .. IE แย่จริงๆเมื่อฉันเขียนโปรแกรมเว็บฉันไม่สนใจ IE เลยเพียงแค่ chrome และ firefox ..........
TechLife

3
@TechLife คุณควรให้เบราว์เซอร์ Android, Safari และโอเปร่าเป็นแนวความคิด แต่ฉันเห็นด้วยกับ 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

1
ยังไม่สามารถใช้งานได้ในเบราว์เซอร์เก่าที่น่าเสียดาย โชคดีที่ฉันเชื่อว่าลูกค้าของฉันจ่ายเงินให้ฉันในเวลาที่ฉันเสียการสนับสนุน IE7 และ IE8
Michael Scheper

2
|| ฟังก์ชั่น () {ส่งคืนวันที่ใหม่ (). getTime ()}
mmm

2
ที่น่าสังเกตว่าให้เวลาต่อเนื่องซึ่งแตกต่างจากเวลาperformance.now() Dateหมายความว่าทุกการโทรที่ตามมาจะรับประกันว่าจะส่งคืนค่าไม่น้อยกว่าการโทรก่อนหน้านี้
ผู้ใช้

48

เท่าที่ฉันรู้ว่าคุณสามารถใช้เวลากับวันที่เท่านั้น

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อะไร?
Andrew Scagnelli

33
+ก็โยนDateไปNumberให้ประทับเวลายูนิกซ์มาตรฐานในหน่วยมิลลิวินาที คุณสามารถรับค่านี้ได้อย่างชัดเจนโดยโทร(new Date()).getTime()
ngryman

9
@mikenelson: ไม่น่ากลัวสำหรับฉันนี้เป็นที่ชัดเจนเมื่อคุณรู้วิธีการทำงานของการบีบบังคับที่กล่าวว่าDate.now()เป็นที่ต้องการในขณะนี้เนื่องจากการสนับสนุนที่มีขนาดใหญ่พอตอนนี้
ngryman

1
ฉันชอบ+มากกว่า.getTime()... มันง่ายกว่าและฉันไม่จำเป็นต้องจำชื่อฟังก์ชั่น

2
@TravisJ ทางลัดที่น่ากลัว? ในการดึงค่าตัวเลขที่มีอยู่ในคอมพิวเตอร์ของคุณแล้วให้คุณสร้างวัตถุให้โทรหาโอเปอเรเตอร์ที่ทดสอบหาอินและทริกเกอร์การแปลงที่เรียกใช้ฟังก์ชัน (valueOf) ที่เรียกวิธีการแปลงคลาสที่เรียกใช้ฟังก์ชัน (getTime) ดึงค่า จากนั้นวัตถุจะถูกทิ้งให้อยู่ในชะตากรรมของมันและหลังจากการวนซ้ำ 1,000 รอบคุณมีวัตถุวันที่ลบ 1,000 รายการที่ต้องมีการรวบรวมขยะแขวนอยู่ที่นั่นซึ่งจะถูกทิ้งทั้งหมดไว้ด้วยกันทันทีและในขณะที่คอมพิวเตอร์ของคุณสงสัยว่าเกิดอะไรขึ้น :) ยอดเยี่ยม!
FrancescoMM

7

หากคุณมีวันที่วัตถุเช่น

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

ดังนั้นจึงมีวิธีการ inbuilt ในจาวาสคริปต์สำหรับการรับวันที่ในรูปแบบมิลลิวินาทีซึ่งเป็นvalueOf ()

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

2

นี่เป็นคำถามที่เก่ามาก - แต่สำหรับการอ้างอิงถ้าคนอื่นดู - requestAnimationFrame()เป็นวิธีที่เหมาะสมในการจัดการภาพเคลื่อนไหวในเบราว์เซอร์สมัยใหม่:

อัปเดต: ลิงก์โมซิลล่าแสดงวิธีการทำเช่นนี้ - ฉันไม่รู้สึกอยากทำซ้ำข้อความที่อยู่ด้านหลังลิงก์)


4
ยินดีต้อนรับสู่Stack Overflow ! คุณอาจต้องการคำอธิบายสั้น ๆ เกี่ยวกับสิ่งrequestAnimationFrameที่จะหยุด "กระโดด" นี้ตามที่อธิบายไว้ในคำถาม ขอบคุณ!
แควนตัส 94 Heavy

2
แม้จะมี RequestAnimationFrame เราก็ไม่ได้คิดว่าอัตราเฟรมจะเท่ากันในทุกแพลตฟอร์มดังนั้นเรายังต้องตรวจสอบเวลาปัจจุบัน
Tom Boutell
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.