Node.js Generators & เปรียบเทียบกับการโทรกลับ
ในบทช่วยสอนนี้ เราจะมาเรียนรู้เกี่ยวกับ Generatorและความแตกต่างกับการโทรกลับ
เครื่องกำเนิดไฟฟ้าคืออะไร?
Generatorค่อนข้างมีชื่อเสียงใน Node.js ในช่วงไม่กี่ครั้งที่ผ่านมา และนั่นอาจเป็นเพราะสิ่งที่พวกเขาสามารถทำได้
- Generatorคือการดำเนินการฟังก์ชันที่สามารถระงับและดำเนินการต่อในภายหลังได้
- Generatorมีประโยชน์เมื่อดำเนินการตามแนวคิดเช่น 'การดำเนินการแบบขี้เกียจ' ซึ่งโดยพื้นฐานแล้วหมายความว่า โดยการระงับการดำเนินการและกลับมาดำเนินการตามต้องการ เราจะสามารถดึงค่าได้เฉพาะเมื่อจำเป็นเท่านั้น
Generatorมี 2 วิธีที่สำคัญด้านล่าง
- วิธีการให้ผลผลิต – มีการเรียกใช้เมธอด Yield ในฟังก์ชันเพื่อหยุดการทำงานของฟังก์ชันที่บรรทัดเฉพาะที่มีการเรียกใช้เมธอด Yield
- วิธีการต่อไป – วิธีการนี้ถูกเรียกจากแอปพลิเคชันหลักเพื่อดำเนินการฟังก์ชันที่มีวิธีผลตอบแทนต่อ การดำเนินการของฟังก์ชันจะดำเนินต่อไปจนถึงวิธีผลตอบแทนถัดไปหรือจนถึงจุดสิ้นสุดของวิธีการ
มาดูตัวอย่างการใช้งานเครื่องกำเนิดไฟฟ้ากัน
ในตัวอย่างของเรา เราจะใช้ฟังก์ชัน Add ง่ายๆ ที่จะบวกตัวเลข 2 ตัว แต่เราจะหยุดการทำงานของเมธอดในจุดต่างๆ เพื่อแสดงให้เห็นว่าสามารถใช้ตัวสร้างได้อย่างไร
function* Add(x) { yield x + 1; var y = yield(null); y = 6 return x + y; } var gen = Add(5); gen.next(); gen.next();
คำอธิบายรหัส
- ขั้นตอนแรกคือการกำหนดฟังก์ชัน "ตัวสร้าง" ของเรา โปรดทราบว่าทำได้โดยการเพิ่ม "*" ลงในคีย์เวิร์ดฟังก์ชัน จากนั้นเราจะกำหนดฟังก์ชันที่เรียกว่า Add ซึ่งรับพารามิเตอร์ x
- คีย์เวิร์ด yield เป็นคีย์เวิร์ดเฉพาะสำหรับเครื่องกำเนิดไฟฟ้า ซึ่งทำให้คีย์เวิร์ดนี้มีประสิทธิภาพในการหยุดการทำงานของฟังก์ชันระหว่างการทำงานใดๆ ดังนั้น ในกรณีนี้ การทำงานของฟังก์ชันจะหยุดลงจนกว่าเราจะเรียกใช้ฟังก์ชัน next() ซึ่งจะดำเนินการในขั้นตอนที่ 4 เมื่อถึงจุดนี้ ค่าของ x จะกลายเป็น 6 และการทำงานของฟังก์ชันจะหยุดลง
- นี่คือจุดที่เราเรียกใช้ฟังก์ชันตัวสร้างก่อนและส่งค่า 5 ไปยังฟังก์ชัน Add ค่านี้จะถูกแทนที่ในพารามิเตอร์ x ของฟังก์ชัน Add
- เมื่อเราเรียกใช้ฟังก์ชัน next() ฟังก์ชัน Add() จะกลับมาดำเนินการอีกครั้ง เมื่อคำสั่งถัดไป var y= Yield(null) จะถูกดำเนินการ ฟังก์ชัน Add() จะหยุดดำเนินการอีกครั้ง
- หลังจากเรียกใช้ฟังก์ชัน next() อีกครั้ง คำสั่งถัดไปจะทำงาน และค่ารวมของ x=5 และ y=6 จะถูกบวกและส่งคืน
การโทรกลับเทียบกับเครื่องกำเนิดไฟฟ้า
Generators ใช้เพื่อแก้ปัญหาที่เรียกว่า callback hell บางครั้งฟังก์ชันการเรียกกลับจะซ้อนกันมากในระหว่างการพัฒนาแอปพลิเคชัน Node.js จนซับซ้อนเกินกว่าจะใช้ฟังก์ชันการเรียกกลับได้
นี่คือจุดที่เครื่องกำเนิดไฟฟ้ามีประโยชน์ ตัวอย่างที่พบบ่อยที่สุดคือการสร้างฟังก์ชันตัวจับเวลา
มาดูตัวอย่างด้านล่างกันว่าตัวสร้างสามารถมีประโยชน์อย่างไรเมื่อเทียบกับคอลแบ็ก
ตัวอย่างของเราจะสร้างฟังก์ชันการหน่วงเวลาอย่างง่าย จากนั้นเราต้องการเรียกฟังก์ชันนี้ซึ่งมีความล่าช้า 1000, 2000 และ 3000 ms
ขั้นตอน 1) กำหนดฟังก์ชันการโทรกลับของเราด้วยโค้ดการหน่วงเวลาที่จำเป็น
function Timedelay(ptime, callback) { setTimeout(function() { callback("Pausing for " + ptime); }, time); }
คำอธิบายรหัส
- ที่นี่เรากำลังสร้างฟังก์ชันที่เรียกว่า Timedelay พร้อมด้วยพารามิเตอร์ที่เรียกว่า ptime การดำเนินการนี้จะใช้เวลาล่าช้าตามที่จำเป็นซึ่งเราต้องการแนะนำในใบสมัครของเรา
- ขั้นตอนถัดไปคือการสร้างข้อความที่จะแสดงต่อผู้ใช้โดยแจ้งว่าแอปพลิเคชันจะหยุดชั่วคราวเป็นเวลาหลายมิลลิวินาที
ขั้นตอน 2) ตอนนี้เรามาดูโค้ดถ้าเรารวมการโทรกลับไว้ด้วย สมมติว่าเราต้องการรวมการโทรกลับตามค่า 1000, 2000 และ 3000 มิลลิวินาที โค้ดด้านล่างแสดงให้เห็นว่าเราจะต้องใช้งานสิ่งเหล่านี้โดยใช้การโทรกลับอย่างไร
Timedelay(1000, function(message) { console.log(msg); Timedelay(2000, function(message) { console.log(msg); Timedelay(3000, function(message) { console.log(msg); }) }) })
คำอธิบายรหัส
- เรากำลังเรียก Timedelay ว่าเป็นการโทรกลับโดยมีค่า 1000
- ต่อไปเราต้องการเรียกใช้ฟังก์ชัน Timedelay อีกครั้งโดยมีค่า 2000
- สุดท้ายนี้ เราต้องการเรียกใช้ฟังก์ชัน Timedelay อีกครั้งโดยมีค่า 3000
จากโค้ดด้านบน คุณจะเห็นว่ามันยุ่งมากขึ้น เนื่องจากเราต้องการเริ่มเรียกใช้ฟังก์ชันหลายๆ ครั้ง
ขั้นตอน 3) ตอนนี้เรามาดูวิธีการนำโค้ดเดียวกันไปใช้โดยใช้ตัวสร้างโค้ดกัน จากโค้ดด้านล่างนี้ คุณจะเห็นว่าการนำฟังก์ชัน Timedelay ไปใช้โดยใช้ตัวสร้างโค้ดนั้นง่ายเพียงใด
function* Messages() { console,log(yield(Timedelay(1000, function(){}))); console,log(yield(Timedelay(2000, function(){}))); console,log(yield(Timedelay(3000, function(){}))); }
คำอธิบายรหัส
- ก่อนอื่นเราจะกำหนดฟังก์ชันตัวสร้างซึ่งจะใช้ในการเรียกใช้ฟังก์ชัน Timedelay ของเรา
- เรากำลังเรียกใช้ฟังก์ชัน Yield พร้อมกับฟังก์ชัน Timedelay โดยมี 1000 เป็นค่าพารามิเตอร์
- จากนั้นเราจะเรียกใช้ฟังก์ชัน Yield พร้อมกับฟังก์ชัน Timedelay โดยมี 2000 เป็นค่าพารามิเตอร์
- สุดท้ายนี้ เรากำลังเรียกฟังก์ชัน Yield พร้อมกับฟังก์ชัน Timedelay โดยที่ 3000 เป็นค่าพารามิเตอร์
สรุป
Generators ยังสามารถใช้เพื่อบรรเทาปัญหาเกี่ยวกับการโทรกลับแบบซ้อน และช่วยในการลบสิ่งที่เรียกว่านรกการโทรกลับ Generators ใช้เพื่อหยุดการประมวลผลของฟังก์ชัน ซึ่งทำได้โดยใช้เมธอด 'yield' ในฟังก์ชันอะซิงโครนัส