ตัวจับเวลาใน Javascript (setInterval, setTimeout) ตัวอย่างของฟังก์ชัน jQuery setTimeout () Javascript ป้องกันไม่ให้ตัวจับเวลาหลายตัวเรียกใช้ setinterval ในเวลาเดียวกัน
ระยะหมดเวลาของ JavaScript เป็นฟังก์ชัน JavaScript ดั้งเดิมที่รันโค้ดบางส่วนหลังจากหน่วงเวลาที่กำหนด (เป็นมิลลิวินาที) สิ่งนี้มีประโยชน์เมื่อคุณต้องการแสดงป๊อปอัปหลังจากที่ผู้ใช้ใช้เวลาบนเพจของคุณไประยะหนึ่งแล้ว หรือคุณต้องการให้เอฟเฟกต์เริ่มต้นเมื่อคุณวางเคอร์เซอร์ไว้เหนือองค์ประกอบหลังจากผ่านไประยะหนึ่งเท่านั้น ด้วยวิธีนี้ คุณสามารถหลีกเลี่ยงการทริกเกอร์เอฟเฟกต์โดยไม่ได้ตั้งใจได้ หากผู้ใช้เลื่อนเมาส์ไปเหนือโดยไม่ได้ตั้งใจ
ตัวอย่าง setTimeout อย่างง่าย
เพื่อแสดงเอฟเฟกต์ของฟังก์ชันนี้ ฉันขอแนะนำให้ดูการสาธิตต่อไปนี้ ซึ่งหน้าต่างป๊อปอัปจะปรากฏขึ้นหลังจากคลิกปุ่มสองวินาที
ดูการสาธิต
ไวยากรณ์
เอกสาร MDN มีไวยากรณ์ต่อไปนี้สำหรับ setTimeout:
var timeoutID = window.setTimeout (ฟังก์ชัน,); var timeoutID = window.setTimeout (รหัส,);
- timeoutID เป็นรหัสตัวเลขที่สามารถใช้ร่วมกับ clearTimeout () เพื่อปิดใช้งานตัวจับเวลา
- func เป็นฟังก์ชันที่จะดำเนินการ
- รหัส ( ในไวยากรณ์ทางเลือก) - บรรทัดของรหัสที่จะดำเนินการ;
- หน่วงเวลา - ระยะเวลาของการหน่วงเวลาเป็นมิลลิวินาทีหลังจากที่ฟังก์ชันจะทำงาน ค่าเริ่มต้นคือ 0
setTimeout กับ window.setTimeout
ไวยากรณ์ข้างต้นใช้ window.setTimeout ทำไม?
อันที่จริง setTimeout และ window.setTimeout เป็นฟังก์ชันเดียวกัน ข้อแตกต่างเพียงอย่างเดียวคือในนิพจน์ที่สอง เราใช้เมธอด setTimeout เป็นคุณสมบัติของอ็อบเจ็กต์หน้าต่างส่วนกลาง
โดยส่วนตัวแล้ว ฉันคิดว่าสิ่งนี้ทำให้โค้ดซับซ้อนมากเท่านั้น หากเราต้องกำหนดวิธีการหมดเวลาของ JavaScript ทางเลือกที่สามารถพบได้และส่งคืนตามลำดับความสำคัญ เราจะพบปัญหาที่ใหญ่กว่านั้นอีก
สำหรับบทช่วยสอนนี้ ฉันไม่ต้องการยุ่งกับวัตถุหน้าต่าง แต่โดยทั่วไปแล้ว จะขึ้นอยู่กับคุณว่าจะใช้รูปแบบใด
ตัวอย่างการใช้
นี่อาจเป็นชื่อของฟังก์ชัน:
ฟังก์ชั่นระเบิด () (แจ้งเตือน ("บูม!");) setTimeout (ระเบิด 2000);
ตัวแปรที่อ้างถึงฟังก์ชัน:
var ระเบิด = ฟังก์ชั่น () (การแจ้งเตือน ("บูม!");); setTimeout (ระเบิด 2000);
หรือฟังก์ชั่นที่ไม่ระบุชื่อ:
setTimeout (ฟังก์ชัน () (การแจ้งเตือน ("บูม!");), 2000);
- โค้ดดังกล่าวมีการรับรู้ได้ไม่ดี ดังนั้นจึงเป็นการยากที่จะปรับปรุงหรือแก้ไขข้อบกพร่องให้ทันสมัย
- มันเกี่ยวข้องกับการใช้วิธีการ eval () ซึ่งอาจเป็นช่องโหว่ที่อาจเกิดขึ้น
- วิธีนี้ช้ากว่าวิธีอื่นเพราะต้องรัน ล่ามจาวาสคริปต์.
โปรดทราบว่าเรากำลังใช้วิธีการเตือนสำหรับการหมดเวลาของ JavaScript เพื่อทดสอบโค้ด
ส่งพารามิเตอร์ไปที่ setTimout
ในครั้งแรก ( นอกจากนี้ข้ามเบราว์เซอร์) ตัวแปร เราส่งพารามิเตอร์ไปยังฟังก์ชันเรียกกลับที่ดำเนินการด้วย setTimeout
ในตัวอย่างต่อไปนี้ เราแยกคำทักทายแบบสุ่มจากอาร์เรย์คำทักทาย และส่งผ่านเป็นพารามิเตอร์ไปยังฟังก์ชันgreet () ซึ่งดำเนินการโดย setTimeout โดยมีการหน่วงเวลา 1 วินาที:
ฟังก์ชั่นทักทาย (ทักทาย) (console.log (ทักทาย);) ฟังก์ชั่น getRandom (arr) (กลับ arr;) var ทักทาย = ["สวัสดี", "Bonjour", "Guten Tag"], randomGreeting = getRandom (ทักทาย); setTimeout (ฟังก์ชัน () (ทักทาย (randomGreeting);), 1000);
ดูการสาธิต
วิธีทางเลือก
ในไวยากรณ์ตอนต้นของบทความนี้ มีเมธอดอื่นที่สามารถใช้เพื่อส่งผ่านพารามิเตอร์ไปยังฟังก์ชันเรียกกลับที่เรียกใช้โดย JavaScript timeout วิธีนี้แสดงถึงผลลัพธ์ของพารามิเตอร์ทั้งหมดหลังจากการหน่วงเวลา
จากตัวอย่างก่อนหน้านี้ เราได้รับ:
setTimeout (ทักทาย 1,000 สุ่มทักทาย);
วิธีการนี้จะไม่ทำงานใน IE 9 และต่ำกว่า โดยที่พารามิเตอร์ที่ส่งผ่านไม่ได้ถูกกำหนดไว้ แต่เพื่อแก้ปัญหานี้ใน MDN มี polyfill พิเศษ.
ปัญหาที่เกี่ยวข้องและ "นี่"
โค้ดที่รันโดย setTimeout ทำงานแยกจากฟังก์ชันที่เรียกใช้ ด้วยเหตุนี้ เราจึงประสบปัญหาบางประการ จึงสามารถใช้คีย์เวิร์ดนี้เป็นแนวทางแก้ไขได้
var person = (firstName: "Jim", Introduction: function () (console.log ("Hi, I" m "+ this.firstName);)); person.introduce (); // ผลลัพธ์: สวัสดี ฉัน" m จิม setTimeout (person.introduction, 50); // ผลลัพธ์: สวัสดี ฉัน "ไม่ได้กำหนด"
สาเหตุของข้อสรุปนี้มาจากข้อเท็จจริงที่ว่าในตัวอย่างแรกสิ่งนี้นำไปสู่วัตถุบุคคล และในตัวอย่างที่สองชี้ไปที่วัตถุหน้าต่างส่วนกลาง ซึ่งไม่มีคุณสมบัติ firstName
คุณสามารถใช้หลายวิธีในการขจัดความไม่สอดคล้องนี้:
บังคับให้ตั้งค่านี้
ซึ่งสามารถทำได้โดยใช้การผูก () ซึ่งเป็นวิธีการที่สร้างฟังก์ชันใหม่ที่เมื่อเรียกว่าเป็นค่าของคีย์นี้ จะใช้ค่าเฉพาะ ในกรณีของเราบุคคลที่ระบุจะคัดค้าน สิ่งนี้ทำให้เราเป็นผล:
setTimeout (person.introduction.bind (คน), 50);
หมายเหตุ: วิธีการผูกถูกนำมาใช้ใน ECMAScript 5 ซึ่งหมายความว่าจะใช้งานได้ในเบราว์เซอร์รุ่นใหม่เท่านั้น ในส่วนอื่นๆ คุณจะได้รับข้อผิดพลาดรันไทม์เมื่อคุณใช้มัน JavaScript "ข้อผิดพลาดการหมดเวลาของฟังก์ชัน".
ใช้ห้องสมุด
ไลบรารีจำนวนมากมีฟังก์ชันในตัวที่จำเป็นในการแก้ปัญหานี้ ตัวอย่างเช่น เมธอด jQuery.proxy () ใช้ฟังก์ชันและคืนค่าฟังก์ชันใหม่ ซึ่งจะใช้บริบทเฉพาะเสมอ ในกรณีของเรา บริบทจะเป็น:
setTimeout ($. พร็อกซี่ (person.introduction, บุคคล), 50);
ดูการสาธิต
ปิดตัวจับเวลา
ค่าที่ส่งคืนของ setTimeout เป็นรหัสตัวเลขที่สามารถใช้เพื่อปิดใช้งานตัวจับเวลาโดยใช้ฟังก์ชัน clearTimeout ():
ตัวจับเวลา var = setTimeout (myFunction, 3000); clearTimeout (ตัวจับเวลา);
มาดูการทำงานกัน ในตัวอย่างถัดไป หากคุณคลิกที่ปุ่ม " เริ่มนับถอยหลัง” การนับถอยหลังเริ่มต้นขึ้น หลังจากเสร็จสิ้นลูกแมวจะได้รับของพวกเขา แต่ถ้าคุณกดปุ่ม " หยุดนับถอยหลัง" ระยะหมดเวลาของ JavaScript จะหยุดและรีเซ็ต
ดูตัวอย่าง
มาสรุปกัน
setTimeout เป็นฟังก์ชันแบบอะซิงโครนัส ซึ่งหมายความว่าการเรียกที่ได้รับไปยังฟังก์ชันนี้จะถูกจัดคิวและจะถูกดำเนินการหลังจากการดำเนินการอื่นๆ ทั้งหมดบนสแต็กเสร็จสิ้นแล้วเท่านั้น ไม่สามารถทำงานพร้อมกันกับฟังก์ชันอื่นหรือแยกเธรดได้
เป็นสิ่งสำคัญอย่างยิ่งที่จะต้องเข้าใจว่าตัวจับเวลา JavaScript ทำงานอย่างไร บ่อยครั้งที่พฤติกรรมของพวกเขาไม่ตรงกับการรับรู้โดยสัญชาตญาณของเราเกี่ยวกับมัลติเธรด และนี่เป็นเพราะความจริงที่ว่าพวกมันทำงานบนเธรดเดียวกัน มาดูฟังก์ชันสี่อย่างที่เราสามารถควบคุมตัวจับเวลาได้:
- var id = setTimeout (fn, หน่วงเวลา); - สร้างตัวจับเวลาอย่างง่ายที่จะเรียกใช้ฟังก์ชันที่ระบุหลังจากหน่วงเวลาที่ระบุ ฟังก์ชันส่งคืน ID ที่ไม่ซ้ำซึ่งตัวจับเวลาสามารถหยุดชั่วคราวได้
- var id = setInterval (fn, หน่วงเวลา); - คล้ายกับ setTimeout แต่เรียกใช้ฟังก์ชันอย่างต่อเนื่องตามช่วงเวลาที่กำหนด (จนกว่าจะหยุด)
- clearInterval (id) ;, clearTimeout (id); - ยอมรับ ID ตัวจับเวลา (ส่งคืนโดยหนึ่งในฟังก์ชันที่อธิบายไว้ข้างต้น) และหยุดการดำเนินการของการโทรกลับ "a.
มีข้อมูลมากมายในรูปนี้ให้เข้าใจ แต่การทำความเข้าใจสิ่งนี้จะทำให้คุณเข้าใจอย่างลึกซึ้งยิ่งขึ้นว่า JavaScript ทำงานแบบอะซิงโครนัสทำงานอย่างไร ไดอะแกรมนี้แสดงเวลาในแนวตั้งเป็นมิลลิวินาที และบล็อคสีน้ำเงินแสดงถึงบล็อคของโค้ด JavaScript ที่ดำเนินการ ตัวอย่างเช่น บล็อกแรกทำงานโดยเฉลี่ยใน 18 มิลลิวินาที การคลิกเมาส์จะบล็อกการทำงานประมาณ 11 มิลลิวินาที เป็นต้น
JavaScript สามารถรันโค้ดได้เพียงอันเดียว (เนื่องจากลักษณะการประมวลผลแบบเธรดเดียว) ซึ่งแต่ละโค้ดจะบล็อกการดำเนินการของเหตุการณ์อะซิงโครนัสอื่นๆ ซึ่งหมายความว่าเมื่อมีเหตุการณ์แบบอะซิงโครนัสเกิดขึ้น (เช่น การคลิกเมาส์ การเรียกตัวจับเวลา หรือคำขอ XMLHttp ที่เสร็จสมบูรณ์) เหตุการณ์นั้นจะถูกเพิ่มลงในคิวและดำเนินการในภายหลัง (แน่นอนว่า การนำไปใช้นั้นแตกต่างกันไปตามเบราว์เซอร์ แต่ ยอมเรียกสิ่งนี้ว่า "คิว") ...
เริ่มต้นด้วย สมมติว่าตัวจับเวลาสองตัวเริ่มต้นภายในบล็อก JavaScript: setTimeout ที่มีการหน่วงเวลา 10ms และ setInterval โดยมีการหน่วงเวลาเท่ากัน ขึ้นอยู่กับเวลาที่เริ่มจับเวลา มันจะเริ่มทำงานในขณะที่เรายังไม่เสร็จสิ้นบล็อกแรกของรหัส อย่างไรก็ตาม โปรดทราบว่าจะไม่ยิงทันที (ไม่สามารถทำได้เนื่องจากเธรดเดียว) ฟังก์ชันที่เลื่อนออกไปจะถูกจัดคิวและดำเนินการในเวลาที่พร้อมใช้งานถัดไปแทน
นอกจากนี้ ในระหว่างการดำเนินการบล็อก JavaScript แรก การคลิกเมาส์จะเกิดขึ้น ตัวจัดการสำหรับเหตุการณ์แบบอะซิงโครนัสนี้ (และเป็นแบบอะซิงโครนัส เนื่องจากเราไม่สามารถคาดการณ์ได้) ไม่สามารถดำเนินการได้โดยตรงในขณะนี้ ดังนั้นจึงเข้าสู่คิว เช่น ตัวจับเวลา
หลังจากรันบล็อกแรกของโค้ด JavaScript แล้ว เบราว์เซอร์จะถามคำถามว่า "กำลังรอการดำเนินการคืออะไร" ในกรณีนี้ ตัวจัดการการคลิกเมาส์และตัวจับเวลาอยู่ในสถานะรอดำเนินการ เบราว์เซอร์จะเลือกหนึ่งในนั้น (ตัวจัดการการคลิก) และดำเนินการ ตัวจับเวลาจะรอช่วงเวลาถัดไปในคิวการดำเนินการ
โปรดทราบว่าในขณะที่ตัวจัดการการคลิกเมาส์กำลังทำงาน การเรียกกลับช่วงเวลาแรกจะเริ่มต้นขึ้น เช่นเดียวกับตัวจับเวลาการโทรกลับจะถูกจัดคิว อย่างไรก็ตาม โปรดทราบว่าเมื่อช่วงเวลาเริ่มทำงานอีกครั้ง (ในขณะที่การเรียกกลับของตัวจับเวลากำลังทำงาน) จะถูกลบออกจากคิว หากการเรียกตามช่วงเวลาทั้งหมด "ถูกเข้าคิวในขณะที่โค้ดจำนวนมากกำลังทำงาน มันจะส่งผลให้มีฟังก์ชันจำนวนมากที่รอการเรียกโดยไม่ชักช้าระหว่างการเสร็จสิ้น เบราว์เซอร์มักจะรอจนกว่าจะไม่มีฟังก์ชันเหลืออยู่ใน ก่อนเพิ่มคิวอื่นเข้าไป
ดังนั้น เราสามารถสังเกตกรณีที่การเปิดใช้งานการเรียกกลับแบบช่วงเวลาครั้งที่สามเกิดขึ้นพร้อมกับช่วงเวลาที่ดำเนินการไปแล้ว สิ่งนี้แสดงให้เห็นจุดสำคัญ: ช่วงเวลาไม่สนใจสิ่งที่กำลังทำงานอยู่ ช่วงเวลาเหล่านี้จะถูกเพิ่มลงในคิวโดยไม่คำนึงถึงระยะเวลาหน่วงระหว่างการดำเนินการ
สุดท้าย หลังจากที่การเรียกกลับช่วงเวลาที่สองเสร็จสิ้น เราจะเห็นว่าไม่มีอะไรเหลือให้กลไก JavaScript ดำเนินการ ซึ่งหมายความว่าเบราว์เซอร์กำลังรอเหตุการณ์แบบอะซิงโครนัสใหม่อีกครั้ง สิ่งนี้จะเกิดขึ้นที่เครื่องหมาย 50ms ซึ่งการเรียกกลับแบบช่วงเวลาจะเริ่มขึ้นอีกครั้ง ณ จุดนี้ จะไม่มีอะไรกั้นมันจึงจะทำงานทันที
มาดูตัวอย่างที่แสดงให้เห็นความแตกต่างระหว่าง setTimeout และ setInterval กัน
setTimeout (ฟังก์ชัน () (/ * บล็อกยาวของรหัส ... * / setTimeout (arguments.callee, 10);), 10); setInterval (ฟังก์ชัน () (/ * บล็อกยาวของรหัส ... * /), 10);
ทั้งสองตัวเลือกนี้เทียบเท่ากันในแวบแรก แต่ในความเป็นจริงแล้วไม่เป็นเช่นนั้น โค้ดที่ใช้ setTimeout จะมีความล่าช้าอย่างน้อย 10 มิลลิวินาทีหลังจากการโทรครั้งก่อนเสมอ (อาจมากกว่านั้นได้ แต่จะไม่มีวันลดลง) ในขณะที่โค้ดที่ใช้ setInterval มักจะถูกเรียกทุกๆ 10 มิลลิวินาทีโดยไม่คำนึงว่าการโทรครั้งก่อนจะถูกดำเนินการเมื่อใด
สรุปข้างต้น:
- เอ็นจิ้น JavaScript ใช้สภาพแวดล้อมแบบเธรดเดียว เปลี่ยนเหตุการณ์แบบอะซิงโครนัสเป็นคิวที่รอดำเนินการ
- ฟังก์ชัน setTimeout และ setInterval ทำงานด้วยวิธีที่แตกต่างกันโดยพื้นฐานในโค้ดแบบอะซิงโครนัส
- หากไม่สามารถดำเนินการจับเวลาได้ในขณะนี้ จะล่าช้าไปจนถึงจุดดำเนินการถัดไป (ซึ่งจะนานกว่าการหน่วงเวลาที่ต้องการ)
- ช่วงเวลา (setInterval) สามารถดำเนินการได้ทีละรายการโดยไม่ชักช้า หากการดำเนินการใช้เวลานานกว่าการหน่วงเวลาที่ระบุ
ทั้งหมดนี้เป็นข้อมูลที่สำคัญอย่างยิ่งต่อการพัฒนา การรู้ว่ากลไก JavaScript ทำงานอย่างไร โดยเฉพาะอย่างยิ่งกับเหตุการณ์แบบอะซิงโครนัสจำนวนมาก (ซึ่งมักเกิดขึ้น) จะเป็นการวางรากฐานที่ยอดเยี่ยมสำหรับการสร้างแอปพลิเคชันขั้นสูง
- จาก:
- ลงทะเบียน: 2014.07.08
- กระทู้: 3,896
- ชอบ: 497
หัวข้อ: SetTimeOut และ SetInterval ไหนดีกว่าที่จะใช้ใน JavaScript?
หากต้องการเรียกใช้โค้ดหลายครั้งในช่วงเวลาปกติ ให้ใช้ฟังก์ชัน setInterval... อย่างไรก็ตาม มีข้อเสียหลายประการ ซึ่งส่วนใหญ่เป็นพฤติกรรมที่แตกต่างกันในเบราว์เซอร์ต่างๆ
ความแตกต่างแรกคือความแตกต่างเมื่อตั้งตัวจับเวลาสำหรับการเริ่มต้นครั้งต่อไป มาสร้างการทดสอบเล็กๆ กัน: เราจะวัดระยะเวลาที่ผ่านไปตั้งแต่เริ่มต้นการเรียกใช้ครั้งก่อนและจากจุดสิ้นสุด
var d1 = วันที่ใหม่ (), d2 = วันที่ใหม่ (); setInterval (ฟังก์ชัน () (var d = new Date (); document.body.innerHTML + = (d - d1) + "" + (d - d2) + "
"; // ใส่ป้ายกำกับที่จุดเริ่มต้นของฟังก์ชัน d1 = new Date (); while (new Date () - d1< 200); // ничего не делаем 200 миллисекунд
// И в конце функции
d2 = new Date();
}, 1000);
ผลลัพธ์จะเป็นข้อมูลเริ่มต้นจากบรรทัดที่สอง
ใน Firefox, Opera, Safari และ Chrome สถานการณ์จะคล้ายกัน: ตัวเลขแรกจะเท่ากับ 1,000 โดยประมาณ ตัวที่สอง - น้อยกว่า 200 ความแตกต่างจะอยู่ในช่วงของค่าเท่านั้น รูปแบบที่เล็กที่สุดใน Chrome และ Opera
2 ตอบโดย PunBB (แก้ไขโดย PunBB 2017.06.08 16:45)
- จาก: มอสโก, Sovkhoznay 3, apt. 98
- ลงทะเบียน: 2014.07.08
- กระทู้: 3,896
- ชอบ: 497
ความแตกต่างอีกประการหนึ่งที่สังเกตเห็นได้น้อยลงและทำซ้ำได้ยากขึ้น แต่บางครั้งอาจทำให้เกิดปัญหาได้มาก ก็คือการต่อต้านการเปลี่ยนแปลงในเวลาของระบบ หากคุณเรียกใช้การทดสอบครั้งต่อไป
setInterval (ฟังก์ชัน () (document.body.innerHTML = Math.random ();), 500);
และหลังจากเริ่มต้น ตั้งเวลาของระบบกลับเป็นนาที จากนั้นในเบราว์เซอร์ Firefox และ Safari การเปลี่ยนตัวเลขจะหยุดชั่วคราว และหลังจากนั้นหนึ่งนาทีก็จะเริ่มใหม่อีกครั้ง แน่นอน การแปลเวลาของระบบด้วยตนเองเป็นสถานการณ์ที่หายากมาก แต่ระบบจำนวนมากได้รับการกำหนดค่าให้ซิงโครไนซ์เวลากับเซิร์ฟเวอร์บนอินเทอร์เน็ตโดยอัตโนมัติ ดังนั้นในบางสถานการณ์ปัจจัยนี้จึงไม่สามารถละเลยได้
ข้อเสียเล็ก ๆ อีกประการหนึ่งของฟังก์ชัน setInterval ก็คือเพื่อที่จะสามารถหยุดการทำงานของมันได้ คุณต้องจำตัวระบุของมันไว้ที่ใดที่หนึ่ง ซึ่งไม่สะดวกเสมอไป
3 ตอบโดย PunBB
- จาก: มอสโก, Sovkhoznay 3, apt. 98
- ลงทะเบียน: 2014.07.08
- กระทู้: 3,896
- ชอบ: 497
Re: SetTimeOut กับ SetInterval แบบไหนดีกว่ากันใน JavaScript?
เพื่อกำจัดข้อเสียที่ระบุไว้ของ setInterval คุณสามารถใช้ setTimeout หลายรายการ
ทางเลือกที่สำคัญสำหรับ setInterval คือ setTimeout แบบเรียกซ้ำ:
/ ** แทน: var timerId = setInterval (ฟังก์ชัน () (การแจ้งเตือน ("tick"), 2000); * / var timerId = setTimeout (ติ๊กฟังก์ชัน () (การแจ้งเตือน ("tick"); timerId = setTimeout (ขีด, 2000);), 2000);
ในโค้ดด้านบนนี้ การดำเนินการครั้งต่อไปจะถูกกำหนดเวลาไว้ต่อจากอันก่อนหน้า
setTimeout แบบเรียกซ้ำเป็นวิธีการกำหนดเวลาที่ยืดหยุ่นกว่า setInterval เนื่องจากเวลาจนถึงการดำเนินการครั้งต่อไปสามารถกำหนดเวลาต่างกันไป ขึ้นอยู่กับผลลัพธ์ของการดำเนินการปัจจุบัน
ตัวอย่างเช่น เรามีบริการที่สำรวจเซิร์ฟเวอร์เพื่อหาข้อมูลใหม่ทุกๆ 5 วินาที หากเซิร์ฟเวอร์ทำงานหนักเกินไป คุณสามารถเพิ่มช่วงเวลาการโพลเป็น 10, 20, 60 วินาที ... แล้วส่งคืนกลับเมื่อทุกอย่างเป็นมาตรฐาน
หากเรามีงานที่โหลดโปรเซสเซอร์อยู่เป็นประจำ เราสามารถประมาณเวลาที่ใช้ในการดำเนินการและกำหนดเวลาการเปิดตัวครั้งต่อไปไม่ช้าก็เร็ว
4 ตอบโดย PunBB
- จาก: มอสโก, Sovkhoznay 3, apt. 98
- ลงทะเบียน: 2014.07.08
- กระทู้: 3,896
- ชอบ: 497
Re: SetTimeOut กับ SetInterval แบบไหนดีกว่ากันใน JavaScript?
setTimeout แบบเรียกซ้ำรับประกันการหยุดชั่วคราวระหว่างการโทร setInterval ไม่
ลองเปรียบเทียบทั้งสองรหัส อันแรกใช้ setInterval:
var i = 1; setInterval (ฟังก์ชัน () (ฟังก์ชัน (i);), 100);
อันที่สองใช้ setTimeout แบบเรียกซ้ำ:
var i = 1; setTimeout (เรียกใช้ฟังก์ชัน () (func (i); setTimeout (เรียกใช้ 100);), 100);
ด้วย setInterval ตัวจับเวลาภายในจะเริ่มทำงานทุก ๆ 100ms และเรียก func (i):
การหยุดชั่วคราวจริงระหว่างการโทร func กับ setInterval นั้นน้อยกว่าที่ระบุในโค้ด!
นี่เป็นเรื่องปกติเพราะไม่ได้คำนึงถึงเวลาในการทำงานของฟังก์ชัน แต่อย่างใด "กิน" ส่วนหนึ่งของช่วงเวลา
อาจเป็นไปได้ว่า func นั้นซับซ้อนกว่าที่เราคาดไว้และใช้เวลานานกว่า 100 ms ในการดำเนินการ
ในกรณีนี้ ล่ามจะรอให้ฟังก์ชันทำงานจนเสร็จ จากนั้นจึงตรวจสอบตัวจับเวลา และหากเวลาสำหรับการโทร setInterval มาถึงแล้ว (หรือผ่านไปแล้ว) การโทรครั้งต่อไปจะเกิดขึ้นทันที
หากฟังก์ชันใช้เวลานานกว่า setInterval หยุดชั่วคราว การเรียกจะเกิดขึ้นโดยไม่หยุดชะงักเลย
5 ตอบโดย รุ่นพี่
- จาก: เยรูซาเลม
- ลงทะเบียน: 2015.06.02
- กระทู้: 958
- ชอบ: 274
Re: SetTimeOut กับ SetInterval แบบไหนดีกว่ากันใน JavaScript?
ทุกอย่างขึ้นอยู่กับงานที่ทำอยู่ เริ่มแรก SetTimeOut ใช้เพื่อเริ่มตัวจับเวลาหนึ่งครั้ง และ SetInterval เพื่อเริ่มการวนซ้ำ แต่ทั้งสองฟังก์ชันสามารถใช้เพื่อวนซ้ำสคริปต์ได้ ตัวอย่างเช่น หากเรียกใช้ซ้ำในฟังก์ชัน SetTimeOut ฟังก์ชันดังกล่าวจะทำงานในลักษณะที่ใช้งานได้จริงคล้ายกับ SetInterval
ข้อเสียของ SetInterval ในขณะนี้คือไม่คำนึงถึงเวลาดำเนินการของสคริปต์ (ฟังก์ชัน) เอง และหากคุณใช้สำหรับคำขอจำนวนมาก ช่วงเวลาจะลดลงอย่างมากและ อาจแตกต่างกันในเบราว์เซอร์ที่แตกต่างกัน
แต่ฉันขอย้ำอีกครั้งว่า หากฟังก์ชันหรือคำขอถูกย่อให้เล็กสุด ผู้ใช้ปลายทางก็ไม่น่าจะรู้สึกถึงความแตกต่าง
ดังนั้นจะใช้อะไรให้ทุกคนตัดสินใจด้วยตัวเอง
ที่มา: http://learn.javascript.ru/settimeout-setinterval
การใช้งาน JavaScript เกือบทั้งหมดมีตัวจับเวลาการตั้งเวลาภายในที่ช่วยให้คุณกำหนดเวลาการเรียกใช้ฟังก์ชันหลังจากช่วงเวลาที่กำหนด
โดยเฉพาะอย่างยิ่ง คุณลักษณะนี้ได้รับการสนับสนุนในเบราว์เซอร์และในเซิร์ฟเวอร์ Node.JS
setTimeout
ไวยากรณ์:
var timerId = setTimeout (ฟังก์ชัน / รหัส, หน่วงเวลา [, arg1, arg2 ...])ตัวเลือก:
- func / รหัส
- ฟังก์ชันหรือบรรทัดของโค้ดที่จะดำเนินการ
- สตริงได้รับการสนับสนุนสำหรับความเข้ากันได้และไม่แนะนำ
- ล่าช้า
- ดีเลย์เป็นมิลลิวินาที 1000 มิลลิวินาทีเท่ากับ 1 วินาที
- arg1, arg2 ...
- อาร์กิวเมนต์ที่จะส่งต่อไปยังฟังก์ชัน ไม่รองรับใน IE9-
- ฟังก์ชันจะถูกดำเนินการหลังจากเวลาที่ระบุในพารามิเตอร์การหน่วงเวลา
ตัวอย่างเช่น รหัสต่อไปนี้จะเรียก alert ("สวัสดี") หลังจากผ่านไปหนึ่งวินาที:
ฟังก์ชั่น func ()(การแจ้งเตือน ("สวัสดี");) setTimeout (func, 1000);หากอาร์กิวเมนต์แรกเป็นสตริง ล่ามจะสร้างฟังก์ชันที่ไม่ระบุชื่อจากสตริงนั้น
นั่นคือบันทึกดังกล่าวทำงานในลักษณะเดียวกันทุกประการ:
SetTimeout ("การแจ้งเตือน (" สวัสดี ")", 1000);
ใช้ฟังก์ชันที่ไม่ระบุชื่อแทน:
ตั้งค่าหมดเวลา ( การทำงาน ()(แจ้งเตือน ("สวัสดี")), 1,000);
พารามิเตอร์ฟังก์ชันและบริบท
ในเบราว์เซอร์สมัยใหม่ทั้งหมด โดยคำนึงถึง IE10 แล้ว setTimeout ช่วยให้คุณสามารถระบุพารามิเตอร์ของฟังก์ชันได้
ตัวอย่างด้านล่างจะแสดง "Hi, I'm Vasya" ทุกที่ยกเว้น IE9-:
ฟังก์ชั่นบอกว่าสวัสดี (ใคร)(การแจ้งเตือน ("สวัสดีฉันคือ" + ใคร);) setTimeout (sayHi, 1000, "Vasya");... อย่างไรก็ตาม ในกรณีส่วนใหญ่ เราต้องการการสนับสนุนสำหรับ IE เก่า และไม่อนุญาตให้คุณระบุอาร์กิวเมนต์ ดังนั้น เพื่อส่งต่อการโทรจะถูกตัดด้วยฟังก์ชันที่ไม่ระบุชื่อ:
ฟังก์ชั่นบอกว่าสวัสดี (ใคร)(การแจ้งเตือน ("สวัสดี ฉัน" + ใคร);) setTimeout ( การทำงาน ()(สวัสดี ("วาสยา")), 1,000);การโทรผ่าน setTimeout ไม่ผ่านบริบทนี้
โดยเฉพาะอย่างยิ่ง การเรียกเมธอดของอ็อบเจ็กต์ผ่าน setTimeout จะทำงานในบริบทส่วนกลาง ซึ่งอาจนำไปสู่ผลลัพธ์ที่ไม่ถูกต้อง
ตัวอย่างเช่น ให้เรียก user.sayHi () หลังจากผ่านไปหนึ่งวินาที:
ฟังก์ชัน ผู้ใช้ (id) การทำงาน ()(แจ้งเตือน (.id นี้);); ) var user = ผู้ใช้ใหม่ (12345); setTimeout (user.sayสวัสดี 1,000); // คาดไว้ 12345 แต่จะพิมพ์ "undefined"เนื่องจาก setTimeout จะเรียกใช้ฟังก์ชัน user.sayHi ในบริบทส่วนกลาง จึงไม่สามารถเข้าถึงวัตถุผ่านสิ่งนี้ได้
กล่าวอีกนัยหนึ่งการเรียก setTimeout สองครั้งนี้ทำสิ่งเดียวกัน:
// (1) setTimeout หนึ่งบรรทัด (user.sayHi, 1000); // (2) สิ่งเดียวกันในสองบรรทัด var func = user.sayHi; setTimeout (ฟังก์ชัน 1,000);โชคดีที่ปัญหานี้แก้ไขได้ง่ายด้วยการสร้างฟังก์ชันระดับกลาง:
ฟังก์ชัน ผู้ใช้ (id)(นี้ .id = id นี้ .sayHi = การทำงาน ()(แจ้งเตือน (.id นี้);); ) var user = ผู้ใช้ใหม่ (12345); setTimeout ( การทำงาน ()(user.sayHi ();), 1,000);ฟังก์ชัน wrapper ใช้เพื่อส่งผ่านอาร์กิวเมนต์ข้ามเบราว์เซอร์และจัดเก็บบริบทการดำเนินการ
ยกเลิกการดำเนินการ
ฟังก์ชัน setTimeout ส่งคืน timerId ที่สามารถใช้เพื่อยกเลิกการดำเนินการ
ไวยากรณ์:
ClearTimeout (ตัวจับเวลา)
ในตัวอย่างต่อไปนี้ เราตั้งค่าระยะหมดเวลาแล้วลบ (เปลี่ยนใจ) เป็นผลให้ไม่มีอะไรเกิดขึ้น
var timerId = setTimeout ( การทำงาน ()(การแจ้งเตือน (1)), 1,000); clearTimeout (timerId);setInterval
เมธอด setInterval มีไวยากรณ์คล้ายกับ setTimeout
var timerId = setInterval (ฟังก์ชัน / รหัส, หน่วงเวลา [, arg1, arg2 ...])ความหมายของอาร์กิวเมนต์เหมือนกัน แต่ต่างจาก setTimeout ตรงที่มันเริ่มการทำงานของฟังก์ชันไม่ใช่ครั้งเดียว แต่จะทำซ้ำเป็นประจำในช่วงเวลาที่กำหนด คุณสามารถหยุดการดำเนินการได้โดยโทร:
ClearInterval (รหัสจับเวลา)
ตัวอย่างต่อไปนี้ เมื่อเริ่มต้นจะแสดงข้อความทุกๆ สองวินาที จนกว่าคุณจะคลิกที่ปุ่ม Stop:
<ประเภทอินพุต = "ปุ่ม" onclick = "clearInterval (ตัวจับเวลา)" ค่า = "(! LANG: หยุด" > !} <สคริปต์> var i = 1; ตัวจับเวลา var = setInterval ( การทำงาน ()(แจ้งเตือน (i ++)), 2000);สคริปต์>การเข้าคิวและการวางซ้อนการโทรใน setInterval
การเรียก setInterval (ฟังก์ชัน, การหน่วงเวลา) ทำให้ฟังก์ชันทำงานหลังจากช่วงเวลาที่กำหนด แต่มีความละเอียดอ่อนที่นี่
อันที่จริง การหยุดชั่วคราวระหว่างการโทรนั้นน้อยกว่าช่วงเวลาที่กำหนด
ตัวอย่างเช่น ใช้ setInterval (ฟังก์ชัน () (func (i ++)), 100) มันรัน func ทุก ๆ 100ms เพิ่มตัวนับในแต่ละครั้ง
ในภาพด้านล่าง บล็อคสีแดงคือเวลาดำเนินการของ func เวลาระหว่างบล็อกคือเวลาระหว่างการเริ่มต้นของฟังก์ชันและน้อยกว่าค่าหน่วงเวลาที่ตั้งไว้!
กล่าวคือ เบราว์เซอร์จะเริ่มต้นการเรียกใช้ฟังก์ชันอย่างเรียบร้อยทุกๆ 100 มิลลิวินาที โดยไม่คำนึงถึงเวลาดำเนินการของฟังก์ชันเอง
มันเกิดขึ้นที่การดำเนินการของฟังก์ชันใช้เวลานานกว่าการหน่วงเวลา ตัวอย่างเช่น ฟังก์ชันมีความซับซ้อนและเวลาในการตอบสนองน้อย หรือฟังก์ชันประกอบด้วยข้อความแจ้งเตือน / ยืนยัน / พรอมต์ที่บล็อกเธรดการดำเนินการ ในกรณีนี้ สิ่งที่น่าสนใจเริ่มต้นขึ้น
หากไม่สามารถเริ่มฟังก์ชันได้เนื่องจากเบราว์เซอร์ไม่ว่าง ระบบจะเข้าคิวและดำเนินการทันทีที่เบราว์เซอร์ว่าง
รูปภาพด้านล่างแสดงสิ่งที่เกิดขึ้นสำหรับฟังก์ชันที่ใช้เวลานานในการดำเนินการ
การเรียกใช้ฟังก์ชันที่เริ่มต้นโดย setInterval จะถูกเพิ่มในคิวและจะเกิดขึ้นทันทีเมื่อเป็นไปได้:
การรันฟังก์ชันที่สองเกิดขึ้นทันทีหลังจากสิ้นสุดครั้งแรก:
การดำเนินการไม่ได้เข้าคิวมากกว่าหนึ่งครั้ง
หากการดำเนินการของฟังก์ชันใช้เวลานานกว่าการดำเนินการตามกำหนดการหลายครั้ง ฟังก์ชันจะยังคงอยู่ในคิวเพียงครั้งเดียว ดังนั้นจึงไม่มี "การสะสม" ของการเปิดตัว
ในภาพด้านล่าง setInterval พยายามเรียกใช้ฟังก์ชันใน 200ms และจัดคิวการโทร ที่ 300ms และ 400ms ตัวจับเวลาจะตื่นขึ้นอีกครั้ง แต่ไม่มีอะไรเกิดขึ้น
การเรียก setInterval (ฟังก์ชัน, การหน่วงเวลา) ไม่ได้รับประกันความล่าช้าที่แท้จริงระหว่างการดำเนินการ
มีบางครั้งที่การหน่วงเวลาจริงมากกว่าหรือน้อยกว่าที่กำหนด โดยทั่วไปแล้ว อย่างน้อยก็ไม่ใช่ความจริงที่ว่าจะมีความล่าช้าบ้าง
การทำซ้ำ setTimeout ที่ซ้อนกัน
ในกรณีที่ไม่ต้องการเพียงการทำซ้ำตามปกติ แต่จำเป็นต้องมีการหน่วงเวลาระหว่างการเริ่มต้น ควรตั้งค่า setTimeout อีกครั้งทุกครั้งที่ดำเนินการฟังก์ชัน
ด้านล่างนี้คือตัวอย่างที่ส่งการแจ้งเตือนโดยมีช่วงเวลา 2 วินาทีระหว่างกัน
<ประเภทอินพุต = "ปุ่ม" onclick = "clearTimeout (ตัวจับเวลา)" ค่า = "(! LANG: หยุด" > !} <สคริปต์> var i = 1; ตัวจับเวลา var = setTimeout ( เรียกใช้ฟังก์ชัน ()(การแจ้งเตือน (i ++); ตัวจับเวลา = setTimeout (เรียกใช้ 2000);), 2000);สคริปต์>จะมีความล่าช้าคงที่ระหว่างการรันบนไทม์ไลน์การดำเนินการ ภาพประกอบสำหรับความล่าช้า 100ms:
ตัวจับเวลาขั้นต่ำล่าช้า
ตัวจับเวลาเบราว์เซอร์มีเวลาแฝงต่ำสุดที่เป็นไปได้ มันแตกต่างกันไปจากประมาณ 0 ถึง 4ms ในเบราว์เซอร์สมัยใหม่ ในรุ่นเก่าอาจสูงกว่าและถึง 15ms
ตามมาตรฐาน ความล่าช้าขั้นต่ำคือ 4ms ดังนั้นจึงไม่มีความแตกต่างระหว่าง setTimeout (.., 1) และ setTimeout (.., 4)
พฤติกรรมของ setTimeout และ setInterval ที่มีความหน่วงเป็นศูนย์เป็นค่าเฉพาะของเบราว์เซอร์
- ใน Opera setTimeout (.., 0) จะเหมือนกับ setTimeout (.., 4) มันทำงานน้อยกว่า setTimeout (.., 2) นี่คือคุณลักษณะของเบราว์เซอร์นี้
- ใน Internet Explorer setInterval (.., 0) ล่าช้าเป็นศูนย์จะล้มเหลว สิ่งนี้ใช้กับ setInterval โดยเฉพาะเช่น setTimeout (.., 0) ทำงานได้ดี
ความถี่ตอบสนองที่แท้จริง
ทริกเกอร์ได้ไม่บ่อยนัก ในบางกรณี การหน่วงเวลาอาจไม่ใช่ 4ms แต่ 30ms หรือ 1000ms
เบราว์เซอร์ส่วนใหญ่ (เดสก์ท็อปเป็นอันดับแรก) ยังคงรัน setTimeout / setInterval ต่อไปแม้ว่าแท็บจะไม่ทำงานก็ตาม ในเวลาเดียวกัน จำนวนหนึ่ง (Chrome, FF, IE10) จะลดความถี่ของตัวจับเวลาขั้นต่ำลงเหลือ 1 ครั้งต่อวินาที ปรากฎว่าตัวจับเวลาจะทำงานในแท็บ "พื้นหลัง" แต่ไม่ค่อย
เมื่อใช้พลังงานแบตเตอรี่ ในแล็ปท็อป เบราว์เซอร์สามารถลดความถี่ลงได้ เพื่อที่จะรันโค้ดได้บ่อยน้อยลงและประหยัดพลังงานแบตเตอรี่ IE มีชื่อเสียงเป็นพิเศษในเรื่องนี้ การลดลงสามารถทำได้หลายครั้ง ขึ้นอยู่กับการตั้งค่า หากโหลดตัวประมวลผลหนักเกินไป JavaScript อาจไม่สามารถประมวลผลตัวจับเวลาได้ทันเวลา การดำเนินการนี้จะข้ามการรัน setInterval บางส่วน
สรุป: คุณควรได้รับคำแนะนำจากความถี่ 4ms แต่คุณไม่ควรไว้วางใจ
การส่งช่วงเวลาไปยังคอนโซล รหัสที่นับช่วงเวลาระหว่างการโทรจะมีลักษณะดังนี้:
var timeMark = วันที่ใหม่; setTimeout ( ฟังก์ชั่นไป ()(var diff = ใหม่ วันที่ - timeMark; // พิมพ์การหน่วงเวลาอื่นไปยังคอนโซลแทนหน้าคอนโซล .log (แตกต่าง); //จำเวลาที่ลงท้ายได้ // เพื่อวัดการหน่วงเวลาที่แน่นอนระหว่างการโทร timeMark = วันที่ใหม่; setTimeout (ไป 100); ), 100 );เคล็ดลับ setTimeout (func, 0)
เคล็ดลับนี้มีค่าควรแก่การเข้าสู่ประวัติของการแฮ็ก JavaScript
ฟังก์ชันนี้รวมอยู่ใน setTimeout (func, 0) หากคุณต้องการเรียกใช้หลังจากสิ้นสุดสคริปต์ปัจจุบัน
ประเด็นคือ setTimeout ไม่เคยเรียกใช้ฟังก์ชันทันที เขาแค่วางแผนการดำเนินการเท่านั้น แต่ล่าม JavaScript จะเริ่มดำเนินการฟังก์ชันที่วางแผนไว้หลังจากเรียกใช้สคริปต์ปัจจุบันเท่านั้น
ตามมาตรฐาน setTimeout ไม่สามารถเรียกใช้ฟังก์ชันที่มีความล่าช้าเป็น 0 ได้ ดังที่เราได้กล่าวไว้ก่อนหน้านี้โดยปกติแล้วการหน่วงเวลาจะอยู่ที่ 4 มิลลิวินาที แต่สิ่งสำคัญที่นี่คือการดำเนินการไม่ว่าในกรณีใดจะเป็นหลังจากการเรียกใช้โค้ดปัจจุบัน
ตัวอย่างเช่น:
ผลลัพธ์ var; ฟังก์ชั่น showResult ()(การแจ้งเตือน (ผลลัพธ์);) setTimeout (showResult, 0); ผลลัพธ์ = 2 * 2; // จะพิมพ์ 4รวม
เมธอด setInterval (func, หน่วงเวลา) และ setTimeout (func, หน่วงเวลา) อนุญาตให้เรียกใช้ func เป็นประจำ / หนึ่งครั้งหลังจากหน่วงเวลาเป็นมิลลิวินาที
ทั้งสองวิธีส่งคืน ID ตัวจับเวลา มันถูกใช้เพื่อหยุดการดำเนินการโดยเรียก clearInterval / clearTimeout
| | setInterval | setTimeout | || ----------- | ---------- | | เวลา | มีการเรียกตัวจับเวลาอย่างเคร่งครัด หากล่ามไม่ว่าง หนึ่งครั้งจะเข้าสู่คิว เวลาดำเนินการของฟังก์ชันจะไม่ถูกนำมาพิจารณา ดังนั้นช่วงเวลาตั้งแต่สิ้นสุดการทำงานหนึ่งครั้งไปจนถึงจุดเริ่มต้นของการทำงานอื่นอาจแตกต่างกัน | การเรียกซ้ำไปยัง setTimeout จะใช้แทน setInterval ซึ่งจำเป็นต้องมีการหยุดชั่วคราวระหว่างการดำเนินการ | | ล่าช้า | ความล่าช้าขั้นต่ำ: 4ms | ความล่าช้าขั้นต่ำ: 4ms | | คุณสมบัติของเบราว์เซอร์ | ความล่าช้า 0 ไม่ทำงานใน IE | ใน Opera เวลาแฝงเป็นศูนย์จะเท่ากับ 4ms ส่วนความล่าช้าอื่นๆ จะได้รับการจัดการอย่างถูกต้อง รวมถึง 1ms, 2ms และ 3ms ที่ไม่ได้มาตรฐาน |
ในการเขียนโปรแกรมในภาษาสคริปต์ จำเป็นต้องสร้างการหยุดชั่วคราวเป็นระยะ - เพื่อหยุดการทำงานของโปรแกรมชั่วขณะหนึ่ง แล้วจึงทำงานต่อไป ตัวอย่างเช่น ในสคริปต์ VBS และ PHP มีวิธีการดังต่อไปนี้:
VBS: wscript.sleep 1500 (หยุด 1.5 วินาที)
PHP: สลีป (10); (หยุดเป็นเวลา 10 วินาที)
ในระหว่างการหยุดชั่วคราวดังกล่าว ระบบรันไทม์ (PHP หรือ VBS) ไม่ได้ทำอะไร... นักพัฒนาซอฟต์แวร์ที่พยายามใช้สิ่งนี้อย่างสังหรณ์ใจใน Javascript จะรู้สึกประหลาดใจอย่างไม่ราบรื่น ข้อผิดพลาดทั่วไปเมื่อพยายามสร้างการหยุดชั่วคราวใน Javascript จะมีลักษณะดังนี้:
ฟังก์ชัน badtest () (สำหรับ (var i = 1; i< 10; i++) { window.setTimeout("document.getElementById("test1").value += " + i, 900) } }
คุณคิดว่าเมื่อผ่านลูปมาถึงการวาดหลักถัดไปของคุณ setTimeoutจะหยุดการทำงานของ Javascript อย่างตรงไปตรงมา รอ 0.9 วินาที เพิ่มหมายเลขที่ต้องการที่ส่วนท้ายของช่องป้อนข้อมูล จากนั้นจึงทำงานต่อไป แต่แท้จริงแล้วไม่ใช่: setIntervalและ setTimeoutใน Javascript เฉพาะการกระทำ (หรือฟังก์ชัน) ที่ระบุในวงเล็บเท่านั้นที่จะล่าช้า ในตัวอย่างของเรา สิ่งต่อไปนี้จะเกิดขึ้น:
- ผม = 1;
- เลื่อนการเพิ่มหมายเลข "1" ลงในช่องป้อนข้อมูล 0.9 วินาที
- โดยทันทีหลังจากตั้งค่าปัญหานี้แล้ว วงจรจะดำเนินต่อไป: i = 2;
- เลื่อนการเพิ่มหมายเลข "2" ลงในช่องป้อนข้อมูล 0.9 วินาที
โดยทันทีหมายถึง ตัวอย่างเช่น 1 มิลลิวินาที (ซึ่งก็คือ ขนาดเล็กมากเมื่อเทียบกับ 900 มิลลิวินาที): วงจรจะทำงานเกือบจะในทันที โดยสร้างงานที่ค้างอยู่หลายรายการจากจุดเดียวกันของเวลา ซึ่งหมายความว่างาน "การวาด" ที่รอดำเนินการทั้งหมดจะเสร็จสมบูรณ์ในเวลาเดียวกัน โดยไม่มีการหยุดระหว่างการเพิ่มหมายเลขใหม่ รอบเริ่มต้น; ทุกอย่างค้างเป็นเวลา 0.9 วินาที; และ shirrr - ตัวเลขทั้งหมดถูกยิงติดต่อกัน
และในกรณีเช่นนี้การสมัครถูกต้องอย่างไร setTimeout? มันซับซ้อน. ต้องเรียกใช้ฟังก์ชัน ซ้ำๆ(จากภายในฟังก์ชัน ฟังก์ชันเดียวกัน) และเพื่อให้กระบวนการนี้ไม่สิ้นสุด ให้ตั้งค่าเงื่อนไขการหยุด (เช่น ค่าของตัวเลขที่พิมพ์):
ฟังก์ชัน welltest () (ถ้า (i< 9) { document.getElementById("test2").value += ++i window.setTimeout("welltest()", 400) } }
และอีกตัวแปรหนึ่ง ผมจะต้องเริ่มต้นนอกฟังก์ชัน - ตัวอย่างเช่นเช่นนี้:
ตอนนี้ทุกอย่างทำงานได้ตามที่ควรจะเป็น (เราลดเวลาหน่วงจาก 0.9 วิเป็น 0.4 วิ) แต่สำหรับงานดังกล่าว มีเหตุผลมากกว่าที่จะไม่ใช้ setTimeout NS setInterval(แม้ว่าจะต้องใช้สองฟังก์ชัน):
ฟังก์ชัน besttest () (window.i = 0 window.timer1 = window.setInterval ("draw ()", 400)) ฟังก์ชัน draw () (document.getElementById ("test3") ค่า + = ++ i ถ้า (i > = 9) clearInterval (window.timer1))
คุณสมบัติของวิธีการ Javascirpt setIntervalที่มันไม่ผ่าน "เอง" ก็ต้องหยุดด้วยวิธีพิเศษ clearInterval... และเพื่อให้ชัดเจนว่าต้องหยุดทำอะไร งานการดำเนินการที่เลื่อนออกไปจะถูกกำหนดตัวระบุพิเศษ - ตัวจับเวลา: window.timer1 = window.setInterval (...)
ตัวระบุยังสามารถกำหนดให้กับงานที่สร้างโดยวิธีการ setTimeout... รหัสตัวจับเวลาทั้งหมดต้องแตกต่างกัน (ไม่ซ้ำกันภายในหน้าต่างเบราว์เซอร์ปัจจุบัน) จากนั้น คุณสามารถสร้างงานต่างๆ ได้หลายงานในหน้าต่างที่ใช้การดำเนินการที่เลื่อนออกไป และงานเหล่านี้จะดำเนินการแบบคู่ขนาน (คล้ายๆ กัน ถ้าคอมพิวเตอร์มีทรัพยากรเพียงพอ) ซึ่งโดยทั่วไปแล้วจะไม่สามารถทำได้ใน PHP หรือ VBS
ต่อไปนี้คือตัวอย่างหน้าเว็บที่มีตัวจับเวลา Javascript หลายตัวทำงานพร้อมกัน: setinterval.htm (ฟังก์ชัน Javascript ในไฟล์ setinterval.js) การทำงานของตัวนับหน้าทั้งหมด (ยกเว้นเมนู) สามารถหยุดได้โดยการกดปุ่ม Esc ตัวจับเวลาตัวอย่างทั้งหมดขึ้นอยู่กับ "ธรรมชาติ" (ไม่ใช่นามธรรม ฉัน ++) นับถอยหลัง - เวลาหรือระยะทาง "นาฬิกา" ทั้งหมดไม่ซิงโครไนซ์เป็นพิเศษ (เพื่อความชัดเจน) ตัวจับเวลาตามระยะทางใช้ใน "ตัวบ่งชี้" และในเมนูแบบเลื่อนลง (แบบเลื่อนลง)
เมนูแบบเลื่อนลง
เมนูแบบดึงออกของเราเป็นแบบดึงออกจริงๆ (จากใต้ "ส่วนหัว"): มีช่องว่างระหว่างองค์ประกอบเพื่อดูว่าจะดึงออกมาอย่างไร โดยไม่คาดคิด ปรากฏว่าเราไม่สามารถออกจากรายการที่มีความยาวต่างกันได้อย่างราบรื่นเท่ากัน อาจเป็นเพราะประสิทธิภาพของคอมพิวเตอร์ต่ำ (AMD Athlon 999 MHz)
เห็นได้ชัดว่าเพื่อความสวยงามและความกลมกลืน จำเป็นต้องมีรายการเมนูต่างๆ ปรากฏขึ้นพร้อมกัน นั่นคือ รายการที่ยาวกว่าควรหลุดออกมาในอัตราที่เร็วกว่า รายการที่สั้นกว่า - ในอัตราที่ต่ำกว่า ดูเหมือนว่าจะสามารถนำไปใช้ได้ดังนี้:
- เราตั้งเวลาทั้งหมดของ "ออกเดินทาง" เช่น 200 มิลลิวินาที
- หากรายการแบบเลื่อนลงมีความสูง 20 พิกเซล เห็นได้ชัดว่าเราสามารถเลื่อนลงมาหนึ่งพิกเซลในเวลา 10 มิลลิวินาที และใน 200 มิลลิวินาที รายการทั้งหมดจะรวบรวมข้อมูล
- หากเมนูแบบเลื่อนลงสูง 40px เพื่อให้พอดีพร้อมกัน เราต้องเลื่อนลงทีละพิกเซลใน 5 มิลลิวินาที
ตามตรรกะนี้ หากรายการดรอปดาวน์สูง 200 พิกเซล เราต้องเลื่อนลงทีละพิกเซลใน 1 มิลลิวินาที แต่ความเร็วนี้ใช้ไม่ได้บนคอมพิวเตอร์ของเรา - เบราว์เซอร์ไม่มีเวลาวาดตำแหน่งใหม่ของรายการในหนึ่งมิลลิวินาที ใช่. Javascript มีเวลานับ (จะนับอะไร) แต่เบราว์เซอร์ (Firefox) ไม่มีเวลาแสดง สถานการณ์ทั่วไปสำหรับเว็บ
ดังนั้นจึงเป็นไปได้ที่จะทำให้เวลาออกจากเมนูเท่ากันมากหรือน้อยโดยใช้ไม้ค้ำยันเท่านั้นและยังไม่ชัดเจนว่าจะทำงานอย่างไรบนคอมพิวเตอร์ที่เร็วกว่า แต่เราต้องนับหนึ่งที่ช้าที่สุดใช่ไหม? อัลกอริทึม (โดยไม่คำนึงถึงความเร็วของคอมพิวเตอร์) กลายเป็นดังนี้:
- เราตั้งเวลาเช็คเอาต์รวมของรายการ: เวลา = 224 (มิลลิวินาที)
- เราตั้งเวลาขั้นต่ำสำหรับหนึ่งช่วงเวลาในหนึ่งรอบ: หน่วงเวลา = 3 (มิลลิวินาที)
- กำหนดขั้นตอนขั้นต่ำสำหรับการย้ายรายการ: offset = 1 (px)
- เราเปลี่ยนแปลงทั้งหมดนี้ขึ้นอยู่กับความสูงของรายการ: 1) เพิ่มเวลาหน่วง (ช่วงเวลา) ในสัดส่วนผกผันกับความสูงและในสัดส่วนโดยตรงกับเวลาทั้งหมด (ที่ความสูง 224 ค่าสัมประสิทธิ์คือ 1); 2) ถ้าความสูงมากกว่า 40 พิกเซล ให้เพิ่มขั้นตอนขั้นต่ำตามสัดส่วนของความสูง ได้รับค่าคงที่ "40" สำหรับคอมพิวเตอร์ที่ช้าที่สุด การทดสอบกับคอมพิวเตอร์ Pentium 4 CPU 2.53GHz พบว่าตัวเลขเหมือนกันทุกประการ - 40 มิฉะนั้น ตัวจับเวลาจะบ้าคลั่ง รายการไม่เป็นไปตาม
ตอนนี้รายการกำลังเปิดตัวไม่มากก็น้อย สำหรับช่วงเวลาที่ใกล้เคียงกันมากหรือน้อย ในหน้า setinterval.htm
และนี่คือ Bru-mustache:
ฟังก์ชัน slide_do (obj, maxtop, offset) (ถ้า (getTopLeft (obj) .top< maxtop) { obj.style.top = getTopLeft(obj).top + offset } else { if (obj && obj.timer1) { clearInterval(obj.timer1) obj.timer1 = null } } }
ฟังก์ชันนี้เองที่นำรายการที่ซ้อนกันออกจากเมนู อย่างที่คุณเห็น มันง่ายมาก มันยังคงเป็นเพียงการเรียกใช้ด้วยบางอย่างเช่นบรรทัดนี้:
Ts.timer1 = setInterval (ฟังก์ชัน () (slide_do (ts, maxtop, offset)), หน่วงเวลา)
ก่อนเริ่ม ให้คำนวณ maxtop และ offset เหล่านี้ทั้งหมด แล้ววางรายการไว้ที่ตำแหน่ง mintop ฟังก์ชัน "เบื้องต้น" ทำอะไร สไลด์ ()ขนาด 40 เส้น และรวมกันทั้งหมด - ในไฟล์ setinterval.js ใช่ และอึนี้จะไม่ทำงานหากไม่มีสไตล์ชีตที่รวมอยู่