คำนำ
ไฮไลต์ที่ใหญ่ที่สุดของ NodeJS คือรุ่น I/O ที่ขับเคลื่อนด้วยเหตุการณ์ซึ่งทำให้ NodeJS มีความสามารถในการประมวลผลพร้อมกันที่แข็งแกร่งและเหมาะสำหรับการเขียนแอปพลิเคชันเครือข่าย การดำเนินการ I/O ส่วนใหญ่ใน NODEJS เกือบจะเป็นแบบอะซิงโครนัสนั่นคือผลลัพธ์ของการดำเนินการ I/O ของเราโดยทั่วไปจำเป็นต้องประมวลผลในฟังก์ชั่นการโทรกลับเช่นฟังก์ชั่นต่อไปนี้ที่อ่านเนื้อหาของไฟล์:
การคัดลอกรหัสมีดังนี้:
fs.readfile ('/etc/passwd', ฟังก์ชั่น (err, data) {
ถ้า (err) โยน err;
console.log (ข้อมูล);
-
ดังนั้นเราควรทำอย่างไรถ้าเราอ่านสองไฟล์และรวมเนื้อหาของไฟล์ทั้งสองนี้เข้าด้วยกัน? คนส่วนใหญ่ที่ไม่ได้ติดต่อกับ JS อาจทำเช่นนี้:
การคัดลอกรหัสมีดังนี้:
fs.readfile ('/etc/passwd', ฟังก์ชั่น (err, data) {
ถ้า (err) โยน err;
fs.readfile ('/etc/passwd2', ฟังก์ชั่น (err, data2) {
ถ้า (err) โยน err;
// ประมวลผลข้อมูลข้อมูลและ data2 ที่นี่
-
-
หากคุณจัดการกับสถานการณ์ที่คล้ายคลึงกันหลายสถานการณ์จะไม่เป็นไปได้ไหมว่าฟังก์ชั่นการโทรกลับเป็นเลเยอร์ซ้อนกันโดยเลเยอร์? นี่คือสิ่งที่ผู้คนมักจะโทรกลับพีระมิดหรือโทรกลับ (http://callbackhell.com/) และมันก็เป็นปัญหาที่ลำบากที่สุดสำหรับ JS Novice
รหัสซ้อนแบบนี้ได้นำปัญหามากมายมาสู่การพัฒนาซึ่งส่วนใหญ่สะท้อนให้เห็นใน:
1. ความเป็นไปได้ของรหัสจะแย่ลง
2. การดีบักปัญหา
3. เป็นการยากที่จะตรวจสอบหลังจากมีข้อยกเว้นเกิดขึ้น
บทความนี้ส่วนใหญ่แนะนำวิธีจัดการปัญหาการโทรกลับแบบอะซิงโครนัสข้างต้นอย่างหรูหรา
โซลูชันหลัก: ประมวลผลการโทรกลับแบบอะซิงโครนัสซ้ำ
เราสามารถใช้การเรียกซ้ำเป็นเครื่องมือควบคุมการดำเนินการสำหรับรหัส ห่อหุ้มการดำเนินการที่จำเป็นต้องดำเนินการลงในฟังก์ชั่นและควบคุมกระบวนการดำเนินการของรหัสโดยเรียกซ้ำในฟังก์ชันการโทรกลับ โดยไม่ต้องกังวลใจเพิ่มเติมให้พูดคุยเกี่ยวกับเรื่องไร้สาระลองดูที่รหัสก่อนหน้า:
การคัดลอกรหัสมีดังนี้:
var fs = ต้องการ ('fs');
// รายการไฟล์ที่จะประมวลผล
var files = ['file1', 'file2', 'file3'];
ฟังก์ชั่น parsefile () {
if (files.length == 0) {
กลับ;
-
var file = files.shift ();
fs.readfile (ไฟล์, ฟังก์ชัน (err, data) {
// ประมวลผลข้อมูลไฟล์ที่นี่
parsefile (); // หลังการประมวลผลให้ประมวลผลไฟล์ถัดไปผ่านการโทรแบบเรียกซ้ำ
-
-
// เริ่มการประมวลผล
parsefile ();
รหัสข้างต้นได้ประมวลผลไฟล์ในอาร์เรย์เป็นตัวอย่างโดยแนะนำกระบวนการดำเนินการของการควบคุมรหัสผ่านวิธีการเรียกซ้ำ
เป็นการดีที่จะนำไปใช้กับสถานการณ์ง่ายๆเช่น: เราสามารถใช้วิธีนี้ได้โดยการบันทึกข้อมูลในอาร์เรย์ลงในฐานข้อมูลในทางกลับกัน
สามารถแก้ไขปัญหาการโทรกลับแบบอะซิงโครนัสได้ง่าย ๆ อย่างไรก็ตามดูเหมือนว่าจะไม่มีอำนาจที่จะจัดการกับการเรียกกลับแบบอะซิงโครนัสที่ซับซ้อน (เช่นการซิงโครไนซ์ผลลัพธ์ของการดำเนินการแบบอะซิงโครนัสหลายครั้ง)
จุดที่งดงาม: ใช้ห้องสมุดบุคคลที่สามเช่น Async, Q, สัญญาว่าจะจัดการการโทรกลับแบบอะซิงโครนัส
เพื่อที่จะจัดการการโทรกลับที่ซ้อนกันได้ดีขึ้นคุณสามารถพิจารณาใช้ห้องสมุดบุคคลที่สามที่จัดการกับอะซิงโครนัสโดยเฉพาะ แน่นอนถ้าคุณมีความสามารถคุณสามารถเขียนเครื่องมือเสริมสำหรับการประมวลผลแบบอะซิงโครนัสด้วยตัวเอง
ห้องสมุดที่ใช้กันมากที่สุดสำหรับการจัดการการประมวลผลแบบอะซิงโครนัสคือ: Async, Q และสัญญา การตัดสินจากเว็บไซต์ NPMJS.org Async เป็นที่นิยมมากที่สุด ฉันเคยใช้ async มาก่อนและมันค่อนข้างสะดวกและการไหลของการควบคุมการประมวลผลแบบอะซิงโครนัสต่าง ๆ นั้นถูกนำมาใช้อย่างดี
เราจะใช้ async เพื่อประมวลผลรหัสที่เริ่มอ่านสองไฟล์ในเวลาเดียวกันตามที่แสดงด้านล่าง:
การคัดลอกรหัสมีดังนี้:
var async = ต้องการ ('async')
, fs = ต้องการ ('fs');
async.parallel ([
ฟังก์ชั่น (โทรกลับ) {
fs.readfile ('/etc/passwd', ฟังก์ชั่น (err, data) {
ถ้า (err) callback (err);
การโทรกลับ (null, data);
-
-
ฟังก์ชั่น (โทรกลับ) {
fs.readfile ('/etc/passwd2', ฟังก์ชั่น (err, data2) {
ถ้า (err) callback (err);
การโทรกลับ (null, data2);
-
-
-
ฟังก์ชั่น (เอ่อผลลัพธ์) {
// ประมวลผลข้อมูลของข้อมูลและ data2 ที่นี่และเนื้อหาของแต่ละไฟล์ได้มาจากผลลัพธ์
-
ผ่านโมดูล Async กระบวนการดำเนินการแบบอะซิงโครนัสสามารถควบคุมได้ดีซึ่งสามารถแก้ปัญหาการโทรกลับแบบเลเยอร์ได้ รหัสมีความชัดเจนกว่าก่อน แต่ก็ยังไม่สามารถแยกออกจากฟังก์ชั่นการโทรกลับ
ลองคิดดูสิมันจะดีถ้าคุณสามารถจัดการกับอะซิงโครนัสได้โดยไม่ต้องใช้ฟังก์ชั่นการโทรกลับ ถัดไปเรามาพูดคุยเกี่ยวกับการใช้คุณสมบัติใหม่ของ ES6 เพื่อให้บรรลุเป้าหมายนี้
จุดสง่างาม: Embrace ES6 แทนที่ฟังก์ชั่นการโทรกลับและแก้ปัญหาการโทรกลับนรก
โดยวิธีการที่ Ecmascript Harmony (ES6) ได้แนะนำคุณสมบัติใหม่มากมายให้กับ JS นักเรียนที่ไม่รู้จักมากเกี่ยวกับ ES6 สามารถดู Baidu ด้วยตนเองได้
ในการใช้คุณสมบัติใหม่ของ ES6 ใน NodeJS คุณต้องใช้ v0.11.x หรือสูงกว่า
บทความนี้แนะนำการใช้คุณสมบัติเครื่องกำเนิดไฟฟ้าแทนฟังก์ชั่นการโทรกลับ ไม่ทราบเกี่ยวกับเครื่องกำเนิดไฟฟ้าใช่ไหม คุณสามารถตรวจสอบได้ที่นี่
ที่นี่เราใช้สองโมดูล CO และ Thunkify และเราใช้คำสั่ง NPM Install เพื่อติดตั้ง
ใช้ปัญหาที่กล่าวถึงในตอนต้นของบทความนี้เป็นตัวอย่าง โค้ดตัวอย่างที่ใช้คุณลักษณะเครื่องกำเนิดไฟฟ้ามีดังนี้:
การคัดลอกรหัสมีดังนี้:
var fs = ต้องการ ('fs')
, co = ต้องการ ('co')
, thunkify = ต้องการ ('thunkify');
var readfile = thunkify (fs.readfile);
CO (ฟังก์ชั่น *() {
var test1 = ผลผลิต readfile ('test1.txt');
var test2 = ผลผลิต readfile ('test2.txt');
test var = test1.toString () + test2.toString ();
console.log (ทดสอบ);
-
นอกจากนี้ยังง่ายมากที่จะจัดการกับข้อยกเว้นในรหัสเพียงทำแบบนี้:
การคัดลอกรหัสมีดังนี้:
พยายาม {
var test1 = ผลผลิต readfile ('test1.txt');
} catch (e) {
// จัดการข้อยกเว้นที่นี่
-
รหัสนี้มีความสง่างามกว่านี้มากหรือไม่? การจัดการแบบอะซิงโครนัสไม่เหมือนการเขียนรหัสแบบซิงโครนัสหรือไม่?
เฟรมเวิร์กที่ได้รับความนิยมมากที่สุดสำหรับการพัฒนาเว็บในฟิลด์ NodeJS นั้นแสดงออกมา เป็นเรื่องที่ควรค่าแก่การกล่าวถึงว่าสมาชิกหลักของ Express TJ ซึ่งเป็น Master of Express ได้เป็นผู้นำของ Web Framework - KOA ซึ่งอ้างว่าเป็นกรอบการพัฒนาเว็บรุ่นต่อไป KOA ใช้คุณลักษณะของเครื่องกำเนิดไฟฟ้า ES6 เพื่อช่วยให้เราหลีกเลี่ยงการตกอยู่ในเลเยอร์ของการโทรกลับเมื่อพัฒนาระบบเว็บ
สรุป
อ้างประโยคจากโปรโมชั่นโครงการ FIBJS: การโทรกลับน้อยกว่าผู้หญิงมากขึ้น - โทรกลับน้อยกว่าผู้หญิงมากขึ้น