หากคุณคุ้นเคยกับการเขียนโปรแกรม JavaScript ฝั่งไคลเอ็นต์คุณอาจใช้ฟังก์ชั่น settimeout และ setInterval ซึ่งอนุญาตให้ล่าช้าเป็นระยะเวลาหนึ่งก่อนที่จะใช้งานฟังก์ชั่น ตัวอย่างเช่นรหัสต่อไปนี้เมื่อโหลดบนหน้าเว็บหลังจาก 1 วินาที "สวัสดีที่นั่น" จะถูกเพิ่มหลังจากเอกสารหน้าเอกสาร:
การคัดลอกรหัสมีดังนี้:
var onesecond = 1,000 * 1; // หนึ่งวินาที = 1,000 x 1 มิลลิวินาที
settimeout (function () {
document.write ('<p> สวัสดีที่นั่น </p>');
}, onecond);
และ setInterval อนุญาตให้ดำเนินการซ้ำของฟังก์ชั่นตามช่วงเวลาที่กำหนด หากรหัสต่อไปนี้ถูกฉีดลงในหน้าเว็บมันจะทำให้ประโยคต่อไปนี้ "สวัสดีที่นั่น" จะถูกเพิ่มลงในเอกสารหน้าทุกวินาที:
การคัดลอกรหัสมีดังนี้:
var onesecond = 1,000 * 1; // หนึ่งวินาที = 1,000 x 1 มิลลิวินาที
setInterval (function () {
document.write ('<p> สวัสดีที่นั่น </p>');
}, onecond);
เนื่องจากเว็บได้กลายเป็นแพลตฟอร์มสำหรับการสร้างแอพพลิเคชั่นมานานแทนที่จะเป็นหน้าคงที่อย่างง่ายความต้องการที่คล้ายกันนี้จึงเกิดขึ้นมากขึ้นเรื่อย ๆ ฟังก์ชั่นการวางแผนงานเหล่านี้ช่วยให้นักพัฒนาดำเนินการตรวจสอบแบบฟอร์มเป็นระยะเวลาการซิงโครไนซ์ข้อมูลระยะไกลหรือการโต้ตอบ UI ที่ต้องการการตอบกลับล่าช้า โหนดยังใช้วิธีการเหล่านี้อย่างเต็มรูปแบบ ทางฝั่งเซิร์ฟเวอร์คุณสามารถใช้พวกเขาเพื่อทำซ้ำหรือชะลอการดำเนินงานหลายอย่างเช่นการหมดอายุแคชการทำความสะอาดกลุ่มการเชื่อมต่อการหมดอายุเซสชันการสำรวจและอื่น ๆ
ดำเนินการโดยใช้ฟังก์ชันการหน่วงเวลา settimeout
Settimeout สามารถสร้างแผนการดำเนินการที่เรียกใช้ฟังก์ชั่นที่ระบุหนึ่งครั้งในช่วงเวลาหนึ่งในอนาคตเช่น:
การคัดลอกรหัสมีดังนี้:
var timeout_ms = 2000; // 2 วินาที
var timeout = settimeout (function () {
console.log ("หมดเวลา!");
}, timeout_ms);
เช่นเดียวกับไคลเอนต์ JavaScript, Settimeout ยอมรับพารามิเตอร์สองตัว พารามิเตอร์แรกคือฟังก์ชั่นที่ต้องล่าช้าและพารามิเตอร์ที่สองคือเวลาหน่วง (เป็นมิลลิวินาที)
Settimeout ส่งคืนที่จับหมดเวลาซึ่งเป็นวัตถุภายใน คุณสามารถใช้เป็นพารามิเตอร์เพื่อเรียก ClearTimeOut เพื่อยกเลิกตัวจับเวลา ยกเว้นว่าด้ามจับนี้ไม่มีผล
ใช้ ClearTimeOut เพื่อยกเลิกแผนการดำเนินการ
เมื่อได้รับการจัดการหมดเวลาคุณสามารถใช้ ClearTimeOut เพื่อยกเลิกแผนการดำเนินการฟังก์ชั่นเช่นนี้:
การคัดลอกรหัสมีดังนี้:
var timeouttime = 1,000; // หนึ่งวินาที
var timeout = settimeout (function () {
console.log ("หมดเวลา!");
}, เวลาหมดเวลา);
ClearTimeout (หมดเวลา);
ในตัวอย่างนี้ตัวจับเวลาจะไม่ถูกทริกเกอร์และจะไม่ส่งออกคำว่า "หมดเวลา!" นอกจากนี้คุณยังสามารถยกเลิกแผนการดำเนินการได้ตลอดเวลาในอนาคตเช่นตัวอย่างต่อไปนี้:
การคัดลอกรหัสมีดังนี้:
var timeout = settimeout (ฟังก์ชัน A () {
console.log ("หมดเวลา!");
}, 2000);
settimeout (ฟังก์ชั่น b () {
ClearTimeout (หมดเวลา);
}, 1,000);
รหัสระบุสองฟังก์ชั่น A และ B ที่ดำเนินการล่าช้า ฟังก์ชั่น A มีการวางแผนที่จะดำเนินการหลังจาก 2 วินาทีและ B ถูกวางแผนที่จะดำเนินการหลังจาก 1 วินาทีเพราะฟังก์ชั่น B ถูกดำเนินการก่อนและยกเลิกแผนการดำเนินการของ A ดังนั้น A จะไม่ทำงาน
พัฒนาและยกเลิกแผนการดำเนินการซ้ำ ๆ ของฟังก์ชั่น
SetInterval คล้ายกับ SettimeOut แต่จะดำเนินการฟังก์ชั่นซ้ำ ๆ ตามช่วงเวลาที่กำหนด คุณสามารถใช้มันเพื่อทริกเกอร์โปรแกรมเป็นระยะเพื่อทำงานอื่น ๆ ที่ต้องทำซ้ำเช่นการทำความสะอาดการรวบรวมการบันทึกการรับข้อมูลการสำรวจ ฯลฯ
รหัสต่อไปนี้จะส่งออก "เห็บ" ไปยังคอนโซลทุกวินาที:
การคัดลอกรหัสมีดังนี้:
ระยะเวลา var = 1,000; // 1 วินาที
setInterval (function () {
console.log ("tick");
}, ระยะเวลา);
หากคุณไม่ต้องการให้ทำงานตลอดไปคุณสามารถใช้ ClearInterval () เพื่อยกเลิกตัวจับเวลา
SetInterval ส่งคืนการจัดการแผนปฏิบัติการซึ่งสามารถใช้เป็นพารามิเตอร์เพื่อ ClearInterval เพื่อยกเลิกแผนการดำเนินการ:
การคัดลอกรหัสมีดังนี้:
VAR Interval = setInterval (ฟังก์ชัน () {
console.log ("tick");
}, 1,000);
-
ClearInterval (ช่วงเวลา);
ใช้ process.nexttick เพื่อชะลอการดำเนินการฟังก์ชั่นไปยังรอบถัดไปของลูปเหตุการณ์
บางครั้งโปรแกรมเมอร์ JavaScript ของไคลเอนต์ใช้ settimeout (callback, 0) เพื่อชะลองานในช่วงเวลาสั้น ๆ พารามิเตอร์ที่สองคือ 0 มิลลิวินาที มันบอกให้ JavaScript เรียกใช้งานฟังก์ชั่นการโทรกลับนี้ทันทีหลังจากดำเนินการกับเหตุการณ์ที่รอดำเนินการทั้งหมด บางครั้งเทคนิคนี้ใช้เพื่อชะลอการดำเนินการของการดำเนินงานที่ไม่จำเป็นต้องดำเนินการทันที ตัวอย่างเช่นบางครั้งคุณต้องเริ่มเล่นภาพเคลื่อนไหวหรือทำการคำนวณอื่น ๆ หลังจากประมวลผลเหตุการณ์ผู้ใช้
ในโหนดเช่นเดียวกับความหมายที่แท้จริงของ "Event Loop", Event Loop ทำงานในวงที่จัดการกับคิวเหตุการณ์และแต่ละรอบในงานวนรอบเหตุการณ์เรียกว่าเห็บ
คุณสามารถโทรหาฟังก์ชั่นการโทรกลับทุกครั้งที่การวนรอบเหตุการณ์เริ่มต้นการดำเนินการรอบถัดไป
โดยใช้ process.nexttick (การโทรกลับ) แทน settimeout (callback, 0) ฟังก์ชั่นการโทรกลับของคุณจะถูกดำเนินการทันทีหลังจากเหตุการณ์ในคิวถูกประมวลผล มันเร็วกว่าคิวการหมดเวลา JavaScript (วัดตามเวลา CPU)
คุณสามารถชะลอฟังก์ชั่นจนกว่าจะวนรอบเหตุการณ์ถัดไปและเรียกใช้เช่นนี้:
การคัดลอกรหัสมีดังนี้:
process.nexttick (function () {
my_expensing_computation_function ();
-
หมายเหตุ: วัตถุกระบวนการเป็นหนึ่งในไม่กี่วัตถุทั่วโลกในโหนด
การปิดกั้นเหตุการณ์
รันไทม์ของโหนดและจาวาสคริปต์ใช้ลูปเหตุการณ์แบบเธรดเดี่ยว แต่ละลูปรันไทม์ใช้ฟังก์ชันการโทรกลับเพื่อจัดการเหตุการณ์ถัดไปในคิว เมื่อมีการดำเนินการเหตุการณ์ลูปเหตุการณ์จะได้รับผลการดำเนินการและประมวลผลเหตุการณ์ถัดไปซ้ำสิ่งนี้จนกว่าคิวเหตุการณ์จะว่างเปล่า หากการโทรกลับหนึ่งครั้งใช้เวลานานในการเรียกใช้งานลูปเหตุการณ์ไม่สามารถจัดการกับเหตุการณ์ที่รอดำเนินการอื่น ๆ ในช่วงเวลานั้นซึ่งสามารถทำให้แอปพลิเคชันหรือบริการช้ามาก
เมื่อใช้การประมวลผลเหตุการณ์หากใช้ฟังก์ชั่นที่ไวต่อหน่วยความจำหรือโปรเซสเซอร์ที่ไวต่อการประมวลผลลูปเหตุการณ์จะช้าลงและเหตุการณ์จำนวนมากจะสะสมซึ่งไม่สามารถประมวลผลได้ในเวลาหรือแม้แต่บล็อกคิว
ดูตัวอย่างต่อไปนี้ของการปิดกั้นเหตุการณ์ลูป:
การคัดลอกรหัสมีดังนี้:
process.nexttick (ฟังก์ชั่น nexttick1 () {
var a = 0;
ในขณะที่ (จริง) {
A ++;
-
-
process.nexttick (ฟังก์ชั่น nexttick2 () {
console.log ("ติ๊กถัดไป");
-
settimeout (ฟังก์ชั่นหมดเวลา () {
console.log ("หมดเวลา");
}, 1,000);
ในตัวอย่างนี้ฟังก์ชั่น NextTick2 และ TimeOut ไม่มีโอกาสทำงานไม่ว่าพวกเขาจะรอนานแค่ไหนเพราะลูปเหตุการณ์ถูกบล็อกโดยลูปที่ไม่มีที่สิ้นสุดในฟังก์ชั่น NextTick และมันจะไม่ทำงานแม้ว่าฟังก์ชั่นการหมดเวลาจะถูกดำเนินการหลังจาก 1 วินาที
เมื่อใช้ SetTimeOut ฟังก์ชั่นการโทรกลับจะถูกเพิ่มลงในคิวแผนปฏิบัติการและในกรณีนี้พวกเขาจะไม่ได้เพิ่มเข้ากับคิว แม้ว่านี่จะเป็นตัวอย่างที่รุนแรง แต่คุณจะเห็นว่าการใช้งานที่ไวต่อโปรเซสเซอร์สามารถบล็อกหรือชะลอการวนซ้ำเหตุการณ์
ออกจาก Event Loop
การใช้ process.nexttick งานที่ไม่สำคัญสามารถเลื่อนออกไปยังรอบถัดไปของ Event Loop (TICK) ก่อนที่จะดำเนินการซึ่งสามารถปลดปล่อยลูปเหตุการณ์เพื่อให้สามารถดำเนินการต่อเหตุการณ์อื่น ๆ ที่รอดำเนินการต่อไปได้
ดูตัวอย่างต่อไปนี้ หากคุณวางแผนที่จะลบไฟล์ชั่วคราว แต่ไม่ต้องการฟังก์ชั่นการโทรกลับของเหตุการณ์ข้อมูลเพื่อรอการดำเนินการ IO นี้คุณสามารถชะลอมันเช่นนี้:
การคัดลอกรหัสมีดังนี้:
stream.on ("data", function (data) {
Stream.end ("คำตอบของฉัน");
process.nexttick (function () {
fs.unlink ("/path/to/file");
-
-
ใช้ settimeout แทน setInterval เพื่อให้แน่ใจว่าการดำเนินการตามฟังก์ชัน
สมมติว่าคุณกำลังวางแผนที่จะออกแบบฟังก์ชั่นที่เรียกว่า my_async_function ซึ่งสามารถดำเนินการ I/O บางอย่าง (เช่นไฟล์บันทึกการแยกวิเคราะห์) และตั้งใจจะดำเนินการเป็นระยะ คุณสามารถนำไปใช้กับ setInterval เช่นนี้:
การคัดลอกรหัสมีดังนี้:
ช่วงเวลา var = 1000;
setInterval (function () {
my_async_function (function () {
console.log ('my_async_function เสร็จแล้ว!');
-
}, Interval); // หมายเหตุของนักแปล: ฉันเพิ่มก่อนหน้านี้ ", Interval" และผู้เขียนควรพลาดเพราะการพิมพ์ผิด
คุณต้องสามารถตรวจสอบให้แน่ใจว่าฟังก์ชั่นเหล่านี้ไม่ได้ดำเนินการพร้อมกัน แต่ถ้าคุณใช้ setInterval คุณไม่สามารถรับประกันได้ หากฟังก์ชั่น my_async_function ทำงานนานกว่าตัวแปรช่วงเวลาหนึ่งมิลลิวินาทีพวกเขาจะถูกดำเนินการพร้อมกันแทนที่จะเป็นลำดับตามลำดับ
หมายเหตุของนักแปล: (ส่วนตัวหนาด้านล่างถูกเพิ่มโดยนักแปลไม่ใช่เนื้อหาของหนังสือต้นฉบับ)
เพื่ออำนวยความสะดวกในการทำความเข้าใจเนื้อหาส่วนนี้คุณสามารถปรับเปลี่ยนรหัสของผู้แต่งเพื่อให้สามารถทำงานได้จริง:
การคัดลอกรหัสมีดังนี้:
ช่วงเวลา var = 1000;
setInterval (function () {
(ฟังก์ชั่น my_async_function () {
settimeout (function () {
console.log ("1");
}, 5000);
-
}, ช่วงเวลา);
เรียกใช้รหัสนี้และคุณจะพบว่าหลังจากรอ 5 วินาที "สวัสดี" จะส่งออกทุก ๆ 1 วินาที เราคาดหวังว่าหลังจากดำเนินการ MY_ASYNC_FUNCTION ปัจจุบัน (ใช้เวลา 5 วินาที) รอ 1 วินาทีก่อนที่จะดำเนินการ MY_ASYNC_FUNCTION ถัดไปและช่วงเวลาระหว่างเอาต์พุตแต่ละรายการควรเป็น 6 วินาที ผลลัพธ์นี้เป็นเพราะ my_async_function ไม่ได้ดำเนินการอย่างอนุกรม แต่ทำงานในเวลาเดียวกัน
ดังนั้นคุณต้องมีวิธีบังคับช่วงเวลาระหว่างการสิ้นสุดของการดำเนินการของ my_async_function และการเริ่มต้นของการดำเนินการของ my_async_function ถัดไปเป็นเวลาที่ระบุโดยตัวแปรช่วงเวลา คุณสามารถทำได้:
การคัดลอกรหัสมีดังนี้:
ช่วงเวลา var = 1000; // 1 วินาที
(กำหนดการฟังก์ชั่น () {// บรรทัดที่ 3
settimeout (ฟังก์ชั่น do_it () {
my_async_function (function () {// line 5
console.log ('async เสร็จแล้ว!');
กำหนดการ();
-
}, ช่วงเวลา);
- // บรรทัด 10
ในรหัสก่อนหน้าฟังก์ชั่นที่เรียกว่ากำหนดการ (บรรทัดที่ 3) และมีการเรียกใช้ทันทีหลังจากการประกาศ (บรรทัดที่ 10) ฟังก์ชั่นกำหนดเวลาจะเรียกใช้ฟังก์ชัน do_it หลังจาก 1 วินาที (ระบุตามช่วงเวลา) หลังจาก 1 วินาทีฟังก์ชัน my_async_function บนบรรทัด 5 จะถูกเรียก เมื่อมีการดำเนินการมันจะเรียกฟังก์ชันการโทรกลับที่ไม่ระบุชื่อของตัวเอง (บรรทัดที่ 6) ฟังก์ชั่นการโทรกลับที่ไม่ระบุชื่อนี้จะรีเซ็ตแผนปฏิบัติการของ DO_IT อีกครั้งและปล่อยให้มันถูกดำเนินการอีกครั้งหลังจาก 1 วินาทีเพื่อให้รหัสจะเริ่มต้นและดำเนินการอย่างต่อเนื่อง
สรุป
คุณสามารถใช้ฟังก์ชั่น settimeout () เพื่อตั้งค่าแผนปฏิบัติการของฟังก์ชั่นและยกเลิกด้วยฟังก์ชัน ClearTimeOut () คุณยังสามารถใช้ setInterval () เพื่อดำเนินการฟังก์ชั่นบางอย่างซ้ำ ๆ เป็นระยะ ดังนั้นคุณสามารถใช้ ClearInterval () เพื่อยกเลิกแผนการดำเนินการซ้ำนี้
หากลูปเหตุการณ์ถูกบล็อกโดยใช้การดำเนินการที่ไวต่อโปรเซสเซอร์ฟังก์ชั่นที่วางแผนไว้เดิมจะถูกดำเนินการจะล่าช้าและจะไม่ถูกดำเนินการ ดังนั้นอย่าใช้การดำเนินการที่ไวต่อซีพียูภายในลูปเหตุการณ์ นอกจากนี้คุณสามารถใช้ process.nexttick () เพื่อชะลอการดำเนินการของฟังก์ชั่นจนกว่ารอบต่อไปของลูปเหตุการณ์
เมื่อใช้ I/O และ setInterval () ร่วมกันคุณไม่สามารถรับประกันได้ว่ามีการโทรเพียงครั้งเดียวที่อยู่ในช่วงเวลาใด ๆ แต่คุณสามารถใช้ฟังก์ชั่นเรียกซ้ำและฟังก์ชั่น settimeout () เพื่อหลีกเลี่ยงปัญหาที่ยุ่งยากนี้