บทช่วยสอนสัญญา Node.js
ในบทช่วยสอนก่อนหน้านี้ คุณคงเคยเห็นฟังก์ชันคอลแบ็กที่ใช้สำหรับเหตุการณ์แบบอะซิงโครนัสแล้ว แต่บางครั้งฟังก์ชันคอลแบ็กอาจกลายเป็นปัญหาเมื่อเริ่มซ้อนกัน และโปรแกรมเริ่มยาวและซับซ้อนมากขึ้น
สัญญาอะไร?
ก่อนที่เราจะเริ่มต้นด้วยสัญญา เรามาทบทวนฟังก์ชัน “callback” ใน Node.js กันก่อน เราได้เห็นฟังก์ชั่นการโทรกลับเหล่านี้บ่อยมากในบทที่แล้ว ดังนั้นเรามาดูหนึ่งในนั้นกันอย่างรวดเร็ว
ตัวอย่างด้านล่างแสดงข้อมูลโค้ดที่ใช้ในการเชื่อมต่อกับ MongoDB ฐานข้อมูลและดำเนินการอัปเดตหนึ่งในระเบียนในฐานข้อมูล
- ในโค้ดข้างต้น ส่วนของฟังก์ชัน(err,db) เรียกว่าการประกาศฟังก์ชันที่ไม่ระบุชื่อหรือฟังก์ชันโทรกลับ เมื่อ MongoClient สร้างการเชื่อมต่อกับ MongoDB ฐานข้อมูล มันจะกลับไปยังฟังก์ชันการเรียกกลับเมื่อการเชื่อมต่อเสร็จสิ้น ดังนั้น ในแง่หนึ่ง การเชื่อมต่อจะเกิดขึ้นในเบื้องหลัง และเมื่อเสร็จสิ้น มันจะเรียกฟังก์ชันการเรียกกลับของเรา โปรดจำไว้ว่านี่เป็นจุดสำคัญประการหนึ่งของ Node.js ที่จะอนุญาตให้มีการดำเนินการหลายอย่างพร้อมกันได้ และไม่บล็อกผู้ใช้คนใดจากการดำเนินการใดๆ
- บล็อกโค้ดที่สองคือสิ่งที่ได้รับการดำเนินการเมื่อมีการเรียกใช้ฟังก์ชันการโทรกลับจริง ฟังก์ชั่นการโทรกลับเพียงอัพเดตหนึ่งบันทึกในของเรา MongoDB ฐานข้อมูล
แล้วสัญญาอะไรล่ะ? สัญญาเป็นเพียงการปรับปรุงฟังก์ชั่นการโทรกลับใน Node.js ในระหว่างวงจรการพัฒนา อาจมีกรณีที่คุณจะต้องซ้อนฟังก์ชันการโทรกลับหลายรายการไว้ด้วยกัน สิ่งนี้อาจทำให้เกิดความยุ่งเหยิงและยากต่อการดูแลรักษา ณ จุดใดจุดหนึ่ง กล่าวโดยสรุป สัญญาคือการปรับปรุงการโทรกลับที่มุ่งบรรเทาปัญหาเหล่านี้
ไวยากรณ์พื้นฐานของคำสัญญาแสดงไว้ด้านล่าง
var promise = doSomethingAync() promise.then(onFulfilled, onRejected)
- “doSomethingAync” คือฟังก์ชันการโทรกลับหรือแบบอะซิงโครนัสใดๆ ที่ทำการประมวลผลบางประเภท
- คราวนี้ เมื่อกำหนดการเรียกกลับ จะมีค่าที่ส่งคืนเรียกว่า "สัญญา"
- เมื่อส่งคืนคำมั่นสัญญา อาจมีเอาต์พุต 2 รายการ ซึ่งกำหนดโดยคำสั่ง 'then' การดำเนินการอาจประสบความสำเร็จซึ่งแสดงด้วยพารามิเตอร์ 'onFulfilled' หรืออาจมีข้อผิดพลาดซึ่งแสดงด้วยพารามิเตอร์ 'onRejected'
หมายเหตุ ดังนั้นสิ่งสำคัญของสัญญาคือมูลค่าที่ส่งคืน ไม่มีแนวคิดเรื่องค่าตอบแทนเมื่อทำงานกับการโทรกลับปกติใน Node.js เนื่องจากค่าที่ส่งคืน เราจึงสามารถควบคุมวิธีการกำหนดฟังก์ชันการเรียกกลับได้มากขึ้น
ในหัวข้อถัดไป เราจะดูตัวอย่างของคำสัญญาและประโยชน์ที่ได้รับจากการโทรกลับ
โทรกลับตามคำสัญญา
ตอนนี้เรามาดูตัวอย่างว่าเราสามารถใช้ “สัญญา” จากภายในแอปพลิเคชัน Node.js ได้อย่างไร หากต้องการใช้สัญญาในแอปพลิเคชัน Node.js จะต้องดาวน์โหลดและติดตั้งโมดูล 'สัญญา' ก่อน
จากนั้นเราจะแก้ไขโค้ดของเราดังที่แสดงด้านล่าง ซึ่งจะอัปเดตชื่อพนักงานในคอลเลกชัน 'พนักงาน' โดยใช้คำสัญญา
ขั้นตอน 1) การติดตั้งโมดูล NPM
หากต้องการใช้ Promises จากภายในแอปพลิเคชัน Node JS จำเป็นต้องมีโมดูล Promise หากต้องการติดตั้งโมดูลสัญญาให้รันคำสั่งด้านล่าง
สัญญาการติดตั้ง npm
ขั้นตอน 2) แก้ไขโค้ดเพื่อรวมคำสัญญา
var Promise = require('promise'); var MongoClient = require('mongodb').MongoClient; var url = 'mongodb://localhost/EmployeeDB'; MongoClient.connect(url) .then(function(err, db) { db.collection('Employee').updateOne({ "EmployeeName": "Martin" }, { $set: { "EmployeeName": "Mohan" } }); });
คำอธิบายรหัส:-
- ส่วนแรกคือการรวมโมดูล 'สัญญา' ซึ่งจะทำให้เราใช้ฟังก์ชันการทำงานของสัญญาในโค้ดของเรา
- ตอนนี้เราสามารถผนวกฟังก์ชัน 'แล้ว' เข้ากับฟังก์ชัน MongoClient.connect ของเราได้แล้ว ดังนั้นสิ่งนี้จะเกิดขึ้นเมื่อมีการเชื่อมต่อกับฐานข้อมูลแล้ว เราจำเป็นต้องดำเนินการกับข้อมูลโค้ดที่กำหนดไว้หลังจากนั้น
- สุดท้ายนี้ เรากำหนดข้อมูลโค้ดของเราซึ่งทำหน้าที่อัปเดตชื่อพนักงานของพนักงานด้วยชื่อ "Martin" เป็น "Mohan"
หมายเหตุ: -
หากคุณตรวจสอบเนื้อหาของคุณแล้ว MongoDB คุณจะพบว่าหากมีบันทึกที่มีชื่อพนักงานเป็น "Martin" อยู่ ระบบจะอัปเดตเป็น "Mohan"
เพื่อตรวจสอบว่าข้อมูลได้รับการแทรกลงในฐานข้อมูลอย่างถูกต้องแล้ว คุณจำเป็นต้องดำเนินการคำสั่งต่อไปนี้ MongoDB
- ใช้ EmployeeDB
- db.Employee.find({ชื่อพนักงาน :Mohan })
คำสั่งแรกช่วยให้แน่ใจว่าคุณเชื่อมต่อกับฐานข้อมูล EmployeeDb คำสั่งที่สองค้นหาบันทึกซึ่งมีชื่อพนักงานว่า "Mohan"
การจัดการกับคำสัญญาที่ซ้อนกัน
เมื่อกำหนดคำสัญญา จะต้องสังเกตว่าวิธีการ "จากนั้น" นั้นจะคืนคำสัญญาเอง ดังนั้นในแง่หนึ่ง คำสัญญาสามารถซ้อนหรือล่ามโซ่ซึ่งกันและกันได้
ในตัวอย่างด้านล่าง เราใช้การเชื่อมโยงเพื่อกำหนดฟังก์ชันการโทรกลับ 2 ฟังก์ชัน ซึ่งทั้งสองฟังก์ชันจะแทรกบันทึกลงใน MongoDB ฐานข้อมูล
(หมายเหตุ: Chaining เป็นแนวคิดที่ใช้เชื่อมโยงการดำเนินการของวิธีการต่างๆ เข้าด้วยกัน สมมติว่าแอปพลิเคชันของคุณมี 2 วิธีที่เรียกว่า 'methodA' และ 'methodB' และตรรกะเป็นเช่นนั้นที่ควรเรียก 'methodB' หลัง 'methodA' จากนั้นคุณจะเชื่อมโยงการดำเนินการในลักษณะที่ 'methodB' ได้รับการเรียกโดยตรงหลังจาก 'methodA')
สิ่งสำคัญที่ต้องทราบในตัวอย่างนี้ก็คือโค้ดจะสะอาดขึ้น อ่านง่ายขึ้น และบำรุงรักษาได้ง่ายขึ้นด้วยการใช้คำมั่นสัญญาแบบซ้อนกัน
var Promise = require('promise'); var MongoClient = require('mongodb').MongoClient; var url = 'mongodb://localhost/EmployeeDB'; MongoClient.connect(url) .then(function(db) { db.collection('Employee').insertOne({ Employeeid: 4, EmployeeName: "NewEmployee" }) .then(function(db1) { db1.collection('Employee').insertOne({ Employeeid: 5, EmployeeName: "NewEmployee1" }) }) });
คำอธิบายรหัส:-
- ตอนนี้เรากำลังกำหนดประโยค "then" 2 ประโยคซึ่งจะถูกดำเนินการทีละประโยค ในส่วนแรกแล้ว เรากำลังส่งพารามิเตอร์ 'db' ซึ่งมีการเชื่อมต่อฐานข้อมูลของเรา จากนั้นเราจะใช้คุณสมบัติการรวบรวมของการเชื่อมต่อ 'db' เพื่อแทรกบันทึกลงในคอลเลกชัน 'พนักงาน' วิธีการ 'insertOne' ใช้เพื่อแทรกเอกสารจริงลงในคอลเลกชันของพนักงาน
- จากนั้นเราก็ใช้ 2nd แล้วข้อยังเพื่อแทรกบันทึกอื่นลงในฐานข้อมูล
หากคุณตรวจสอบเนื้อหาของคุณแล้ว MongoDB ฐานข้อมูลคุณจะพบว่าบันทึก 2 รายการถูกแทรกลงใน MongoDB ฐานข้อมูล
การสร้างคำสัญญาที่กำหนดเอง
สัญญาที่กำหนดเองสามารถสร้างขึ้นได้โดยใช้โมดูลโหนดที่เรียกว่า 'q' จำเป็นต้องดาวน์โหลดและติดตั้งไลบรารี 'q' โดยใช้ตัวจัดการแพ็คเกจโหนด หลังจากใช้ไลบรารี 'q' แล้ว จะสามารถเรียกเมธอด "denodeify" ซึ่งจะทำให้ฟังก์ชันใดๆ กลายเป็นฟังก์ชันที่ส่งคืนสัญญาได้
ในตัวอย่างด้านล่าง เราจะสร้างฟังก์ชันง่ายๆ ที่เรียกว่า "Add" ซึ่งจะบวกตัวเลข 2 ตัว เราจะแปลงฟังก์ชันนี้ให้เป็นฟังก์ชันเพื่อส่งคืนคำมั่นสัญญา
เมื่อเสร็จแล้ว เราจะใช้สัญญาที่ส่งคืนโดยฟังก์ชัน Add เพื่อแสดงข้อความใน console.log
มาทำตามขั้นตอนด้านล่างเพื่อสร้างฟังก์ชันแบบกำหนดเองของเราเพื่อคืนสัญญา
ขั้นตอน 1) การติดตั้งโมดูล NPM
หากต้องการใช้ 'q' จากภายในแอปพลิเคชัน Node JS จำเป็นต้องมีโมดูล 'q' หากต้องการติดตั้งโมดูล 'q' ให้รันคำสั่งด้านล่าง
ติดตั้ง npm q
ขั้นตอน 2) กำหนดโค้ดต่อไปนี้ซึ่งจะใช้เพื่อสร้างคำมั่นสัญญาแบบกำหนดเอง
คำอธิบายรหัส:-
- บิตแรกคือการรวมไลบรารี 'q' โดยใช้คีย์เวิร์ด need โดยใช้ไลบรารีนี้ เราจะสามารถกำหนดฟังก์ชันใด ๆ เพื่อส่งคืนการโทรกลับได้
- เรากำลังสร้างฟังก์ชันที่เรียกว่า Add ซึ่งจะบวกตัวเลข 2 ตัวที่กำหนดไว้ในตัวแปร a และ b ผลรวมของค่าเหล่านี้จะถูกเก็บไว้ในตัวแปร c
- จากนั้นเราจะใช้ไลบรารี q เพื่อ denodeify (วิธีการที่ใช้ในการแปลงฟังก์ชันใดๆ ให้เป็นฟังก์ชันที่จะส่งคืนคำสัญญา) ฟังก์ชัน Add ของเรา หรือแปลงฟังก์ชัน Add ของเราให้เป็นฟังก์ชันที่ส่งคืนคำสัญญา
- ตอนนี้เราเรียกฟังก์ชัน "เพิ่ม" ของเราและสามารถรับมูลค่าสัญญาคืนได้เนื่องจากขั้นตอนก่อนหน้าที่เราดำเนินการในการ denodeify ฟังก์ชัน Add
- คำสำคัญ 'then' ถูกใช้เพื่อระบุว่าหากดำเนินการฟังก์ชันได้สำเร็จ ให้แสดงสตริง “ฟังก์ชันเพิ่มเติมเสร็จสมบูรณ์” ใน console.log
เมื่อรันโค้ดด้านบนแล้ว เอาต์พุต “ฟังก์ชันการเพิ่มเติมเสร็จสมบูรณ์” จะปรากฏใน console.log ดังแสดงด้านล่าง
สรุป
- การใช้ฟังก์ชันโทรกลับใน Node.js ก็มีข้อเสียเช่นกัน บางครั้งในระหว่างกระบวนการพัฒนา การใช้ฟังก์ชัน callback แบบซ้อนกันอาจทำให้โค้ดยุ่งเหยิงและบำรุงรักษาได้ยาก
- ปัญหาส่วนใหญ่ที่เกิดกับฟังก์ชันการโทรกลับแบบซ้อนกันสามารถบรรเทาได้ด้วยการใช้คำสัญญาและตัวสร้างใน Node.js
- Promise คือค่าที่ส่งคืนโดยฟังก์ชันอะซิงโครนัสเพื่อระบุการเสร็จสมบูรณ์ของการประมวลผลที่ดำเนินการโดยฟังก์ชันอะซิงโครนัส
- Promises สามารถซ้อนกันได้เพื่อทำให้โค้ดดูดียิ่งขึ้นและง่ายต่อการดูแลรักษาเมื่อจำเป็นต้องเรียกใช้ฟังก์ชันอะซิงโครนัสหลังจากฟังก์ชันอะซิงโครนัสอื่น