ฟังก์ชัน Generator ใน JavaScript
ในบทความนี้ เราจะอธิบายฟังก์ชัน Generator ใน JavaScript
YouTube Video
ฟังก์ชัน Generator ใน JavaScript
ฟังก์ชัน Generator ใน JavaScript เป็นฟังก์ชันพิเศษที่แตกต่างจากฟังก์ชันทั่วไป เนื่องจากสามารถดำเนินการแบบ lazy execution และ หยุดชั่วคราวและดำเนินการต่อได้ การเข้าใจฟังก์ชัน Generator จะช่วยให้คุณสามารถจัดการกับการดำเนินงานแบบอะซิงโครนัสและการประมวลผลข้อมูลขนาดใหญ่ได้อย่างมีประสิทธิภาพ ในที่นี้ เราจะอธิบายรายละเอียดเกี่ยวกับวิธีการทำงานของฟังก์ชัน Generator วิธีการใช้งาน และกรณีการใช้จริง
ฟังก์ชัน Generator คืออะไร?
ฟังก์ชัน Generator ถูกกำหนดด้วย function*
(คำจำกัดความของฟังก์ชันที่มีดอกจัน) และแตกต่างจากฟังก์ชันทั่วไป เนื่องจากสามารถหยุดชั่วคราวระหว่างการทำงานและดำเนินการต่อในขณะที่ยังรักษาสถานะเดิมไว้ได้ ฟังก์ชัน Generator ช่วยให้เกิด "lazy execution" และคืนค่าผลลัพธ์ทีละขั้นตอน ซึ่งช่วยให้การจัดการหน่วยความจำและการประมวลผลตามลำดับเป็นไปอย่างมีประสิทธิภาพ
ไวยากรณ์
1function* generatorFunction() {
2 yield 'First value';
3 yield 'Second value';
4 return 'Done';
5}
ในลักษณะนี้ ฟังก์ชัน Generator สามารถมีคำสั่ง yield
หลายตัว และใช้ yield
เพื่อหยุดการทำงานชั่วคราวได้ เมื่อฟังก์ชัน Generator ถูกเรียกใช้งาน เนื้อหาของฟังก์ชันจะไม่ถูกดำเนินการทันที และจะคืนค่า generator object คุณสามารถเรียกใช้เมธอด next()
บนวัตถุนี้เพื่อดำเนินการฟังก์ชันต่อจากจุดที่หยุดไว้
การใช้งานพื้นฐานของฟังก์ชัน Generator
ถัดไป ลองดูตัวอย่างพื้นฐานของการใช้งานฟังก์ชัน Generator
1function* simpleGenerator() {
2 yield 1;
3 yield 2;
4 yield 3;
5}
6
7const gen = simpleGenerator();
8
9console.log(gen.next()); // { value: 1, done: false }
10console.log(gen.next()); // { value: 2, done: false }
11console.log(gen.next()); // { value: 3, done: false }
12console.log(gen.next()); // { value: undefined, done: true }
จุดสำคัญที่ควรทราบคือ Generator จะคืนค่าด้วย yield
ทุกครั้ง และตราบใดที่คุณสมบัติ done
เป็น false
หมายความว่ายังมีค่าที่จะถูกคืนมาอีก การเรียก next()
ครั้งสุดท้ายจะคืนค่า done: true
ซึ่งหมายถึง Generator ได้ทำงานเสร็จสมบูรณ์แล้ว
คีย์เวิร์ด yield
และการหยุดชั่วคราวค่า
yield
เป็นคีย์เวิร์ดที่ระบุจุดที่หยุดชั่วคราวภายในฟังก์ชัน Generator ค่าทางด้านขวาของ yield
จะถูกคืนกลับเมื่อมีการเรียกใช้ next()
นอกจากนี้ yield
ยังรองรับการสื่อสารแบบสองทางอีกด้วย พูดอีกอย่างคือ เมื่อส่งค่าผ่านเป็นอาร์กิวเมนต์ไปยังเมธอด next()
ค่านั้นจะถูกส่งไปยังฟังก์ชัน Generator
1function* generatorWithYield() {
2 const value1 = yield 'First yield';
3 console.log('Received value:', value1);
4 const value2 = yield 'Second yield';
5 console.log('Received value:', value2);
6}
7
8const gen = generatorWithYield();
9
10console.log(gen.next()); // { value: 'First yield', done: false }
11console.log(gen.next('Apple')); // Received value: Apple
12 // { value: 'Second yield', done: false }
13console.log(gen.next('Banana'));// Received value: Banana
14 // { value: undefined, done: true }
ในตัวอย่างนี้ การเรียก next('Apple')
จะส่งค่า 'Apple'
ไปยังฟังก์ชัน Generator ซึ่งค่าดังกล่าวจะถูกใช้งานภายในฟังก์ชัน
การจัดการสถานะของ Generator
Generators สามารถรักษาสถานะระหว่างการทำงานของตน ซึ่งช่วยให้การแสดงผลของลูปยาวหรือการประมวลผลแบบลำดับมีความกระชับ ตัวอย่างต่อไปนี้แสดงการทำงานของ generator ที่สร้างตัวเลขอย่างไม่สิ้นสุด
1function* infiniteGenerator() {
2 let i = 0;
3 while (true) {
4 yield i++;
5 if (i > 10) {
6 break;
7 }
8 }
9}
10
11const gen = infiniteGenerator();
12
13console.log(gen.next().value); // 0
14console.log(gen.next().value); // 1
15console.log(gen.next().value); // 2
16// Continues...
generator นี้สร้างตัวเลขอย่างต่อเนื่องโดยใช้ลูป while(true)
ทำให้คุณสามารถรับค่าได้ตามต้องการ สิ่งนี้ช่วยให้การประมวลผลชุดข้อมูลขนาดใหญ่มีประสิทธิภาพมากขึ้น
การใช้งานของฟังก์ชัน Generator
ฟังก์ชัน Generator เหมาะสำหรับการดำเนินขั้นตอนการประมวลผลหลายขั้นตอนแบบตามลำดับ ตัวอย่างเช่น ฟังก์ชันเหล่านี้มีประโยชน์ในการประมวลผลคำร้อง API แบบตามลำดับหรือการแบ่งและประมวลผลไฟล์ขนาดใหญ่
1function* apiRequestGenerator() {
2 yield fetch('https://codesparklab.com/json/example1.json');
3 yield fetch('https://codesparklab.com/json/example2.json');
4 yield fetch('https://codesparklab.com/json/example3.json');
5}
ดังนั้น generator ที่สามารถใช้สำหรับการประมวลผลแบบอะซิงโครนัสจึงมีประโยชน์อย่างมากในการจัดการข้อมูลแบบตามลำดับอย่างมีประสิทธิภาพ
Asynchronous Generators
Asynchronous generators ซึ่งถูกนำมาใช้ใน ES2018 ช่วยให้คุณสามารถคืนค่าที่เป็นอะซิงโครนัสแบบตามลำดับได้โดยการรวม async
และ yield
สิ่งนี้ทำให้สามารถเขียนกระบวนการประมวลผลแบบอะซิงโครนัสได้อย่างกระชับโดยใช้ร่วมกับ await
ไวยากรณ์
1async function* asyncGenerator() {
2 yield await Promise.resolve(1);
3 yield await Promise.resolve(2);
4 yield await Promise.resolve(3);
5}
6
7const gen = asyncGenerator();
8
9(async () => {
10 for await (const value of gen) {
11 console.log(value); // 1, 2, 3
12 }
13})();
Asynchronous generators สามารถดึงค่าต่าง ๆ ตามลำดับโดยใช้ลูป for await...of
รูปแบบนี้มีประโยชน์อย่างยิ่งเมื่อจัดการกับข้อมูลสตรีมแบบอะซิงโครนัส
ตัวอย่างการใช้งานจริง: การทำให้การประมวลผลแบบอะซิงโครนัสง่ายขึ้นด้วย Generators
ฟังก์ชัน Generator ยังถูกใช้เพื่อลดความซับซ้อนของกระบวนการประมวลผลแบบอะซิงโครนัส ตัวอย่างเช่น โดยการรวม yield
และ Promise
ดังตัวอย่างด้านล่าง คุณสามารถเขียนการดำเนินการแบบอะซิงโครนัสให้ดูเหมือนเป็นแบบซิงโครนัสได้
1function* asyncFlow() {
2 const data1 = yield fetch('https://codesparklab.com/json/example1.json');
3 console.log(data1);
4 const data2 = yield fetch('https://codesparklab.com/json/example2.json');
5 console.log(data2);
6}
7
8const gen = asyncFlow();
9
10function handleAsync(generator) {
11 const next = (promise) => {
12 promise.then((result) => {
13 const { value, done } = generator.next(result);
14 if (!done) {
15 next(value);
16 }
17 });
18 };
19
20 next(generator.next().value);
21}
22
23handleAsync(gen);
โค้ดนี้ทำการร้องขอ API แบบตามลำดับโดยใช้ generator และประมวลผลผลลัพธ์
สรุป
ฟังก์ชัน Generator เป็นหนึ่งในฟีเจอร์ที่ทรงพลังของ JavaScript ที่มีความสามารถในการหยุดและเริ่มการทำงานของฟังก์ชันอีกครั้ง สิ่งนี้ช่วยให้สามารถประมวลผลแบบตามลำดับ การประมวลผลแบบอะซิงโครนัส และการจัดการชุดข้อมูลขนาดใหญ่อย่างมีประสิทธิภาพ การเข้าใจ generator เป็นขั้นตอนสำคัญในการเรียนรู้เทคนิคขั้นสูงใน JavaScript
คุณสามารถติดตามบทความข้างต้นโดยใช้ Visual Studio Code บนช่อง YouTube ของเรา กรุณาตรวจสอบช่อง YouTube ด้วย