โทรกลับนรก
สำหรับโปรแกรมเมอร์ JavaScript การจัดการการเรียกกลับนั้นอบอุ่น แต่การจัดการการโทรกลับที่มีระดับลึกเกินไปนั้นไม่ได้สวยงาม ตัวอย่างโค้ดตัวอย่างต่อไปนี้ใช้การเรียกกลับสามชั้นจากนั้นเติมสมองให้กับเลเยอร์มากขึ้น มันก็เปรี้ยว นี่คือนรกโทรกลับในตำนาน
getDirectories (ฟังก์ชั่น (dirs) {getFiles (dirs [0], ฟังก์ชัน (ไฟล์) {getContent (ไฟล์ [0], ฟังก์ชั่น (ไฟล์, เนื้อหา) {console.log ('ชื่อไฟล์:', ไฟล์); console.log (เนื้อหา);});});}); ฟังก์ชั่น getDirectories (การโทรกลับ) {settimeout (function () {callback (['/home/ben']);}, 1000);} function getFiles (dir, callback) {settimeout (function () {callback (dir + '/test1.txt' settimeout (function () {callback (ไฟล์, 'เนื้อหา');}, 1000)}สารละลาย
มีวิธีแก้ปัญหาแบบอะซิงโครนัสจำนวนมากในระบบนิเวศที่สามารถจัดการกับปัญหาของการโทรกลับนรกเช่น Bluebird, Q ฯลฯ บทความนี้มุ่งเน้นไปที่การสนับสนุนการเขียนโปรแกรมแบบอะซิงโครนัสในข้อกำหนด ECMAScript 6/7
ES6 Promise
สัญญาเป็นทางออกสำหรับการเขียนโปรแกรมแบบอะซิงโครนัสและเครื่องมือที่ทรงพลังในการแก้ปัญหาการโทรกลับนรก
สัญญาได้รับการยอมรับอย่างมากในระบบนิเวศ JavaScript ในปี 2550 เมื่อเฟรมเวิร์ก Dojo เพิ่มฟังก์ชั่นของ Dojo.Deverred ด้วยความนิยมของ dojo.deverred ในปี 2009 Kris Zyp เสนอคำสัญญา CommonJS/ข้อมูลจำเพาะ ต่อจากนั้นมีการดำเนินการตามสัญญาจำนวนมากปรากฏในระบบนิเวศรวมถึง Q.JS, FuturesJS ฯลฯ แน่นอนว่าความนิยมของสัญญาส่วนใหญ่เกิดจากการมีอยู่ของ jQuery แต่ jQuery ไม่สอดคล้องกับสัญญาสามัญชน/ข้อกำหนด จากนั้นอย่างที่คุณเห็นข้อกำหนด ES 6 รวมถึงสัญญา
คำสัญญาอธิบายไว้ใน MDN ดังนี้:
วัตถุสัญญาเป็นพร็อกซีสำหรับค่าส่งคืนซึ่งอาจไม่เป็นที่รู้จักเมื่อสร้างวัตถุสัญญา ช่วยให้คุณระบุวิธีการจัดการเพื่อความสำเร็จหรือความล้มเหลวของการดำเนินการแบบอะซิงโครนัส สิ่งนี้ช่วยให้วิธีการแบบอะซิงโครนัสสามารถส่งคืนค่าเช่นวิธีการซิงโครนัส: วิธีการแบบอะซิงโครนัสส่งคืนค่าผลตอบแทนเดิม
รหัสต่อไปนี้เป็นตัวอย่างในส่วน "การโทรกลับ" ที่นำมาใช้ผ่านสัญญา รหัสไม่ได้ดูกระชับมาก แต่มีการปรับปรุงอย่างมีนัยสำคัญเมื่อเทียบกับการเรียกกลับแบบลำดับชั้นแบบดั้งเดิมและรหัสสามารถบำรุงรักษาได้และอ่านได้มากขึ้น
getDirectories (). จากนั้น (ฟังก์ชั่น (dirs) {return getfiles (dirs [0]);}) จากนั้น (ฟังก์ชั่น (ไฟล์) {return getContent (ไฟล์ [0]);}) จากนั้น (ฟังก์ชั่น (val) {console.log ('filename:', val.file) ฟังก์ชั่น getDirectories () {ส่งคืนสัญญาใหม่ (ฟังก์ชั่น (แก้ไข, ปฏิเสธ) {settimeout (function () {Resolve (['/home/ben']);}, 1000);});} function getFiles (dir) {ส่งคืนสัญญาใหม่ '/test2.txt']);}, 1000);เครื่องกำเนิดไฟฟ้า ES6
การดำเนินการตามสัญญาไม่กระชับเพียงพอเรายังต้องการตัวเลือกที่ดีกว่า CO เป็นหนึ่งในตัวเลือก CO เป็นคอนโทรลเลอร์การไหลแบบอะซิงโครนัสที่ใช้เครื่องกำเนิดไฟฟ้า ก่อนที่จะเข้าใจ CO คุณต้องเข้าใจเครื่องกำเนิดไฟฟ้าก่อน นักเรียนที่คุ้นเคยกับ C# ควรเข้าใจว่ารุ่น C# 2.0 แนะนำคำหลักให้ซ้ำเพื่อทำซ้ำเครื่องกำเนิดไฟฟ้า เครื่องกำเนิดไฟฟ้า ES 6 นั้นคล้ายคลึงกับ C#และยังใช้น้ำตาลไวยากรณ์ผลผลิตและใช้เครื่องจักรของรัฐภายใน สำหรับการใช้งานที่เฉพาะเจาะจงโปรดดูส่วนฟังก์ชั่นเอกสาร MDN* และอ้างอิงถึงบล็อกทีมอัลลีย์ทีมสำหรับความเข้าใจในเชิงลึกของเครื่องกำเนิดไฟฟ้า ใช้ CO เพื่อรวม ES6 Generator อย่างชาญฉลาดและ ES6 สัญญาว่าจะโทรแบบอะซิงโครนัสได้อย่างกลมกลืนมากขึ้น
CO (ฟังก์ชั่น* () {var dirs = ผลผลิต getDirectories (); var files = dielt getFiles (dirs [0]); var contentVal = ผลผลิต getContent (ไฟล์ [0]); console.log ('filename:', contentval.file); console.log (contentval.content);});CO นั้นฉลาดมากและโค้ดหลักของมันสามารถทำให้ตัวอย่างต่อไปนี้ง่ายขึ้น แนวคิดทั่วไปคือการใช้เครื่องกำเนิดไฟฟ้าแบบเรียกซ้ำจนกว่ารัฐจะเสร็จสมบูรณ์แน่นอนว่า CO ทำมากขึ้น
rungenerator (); ฟังก์ชั่น* run () {var dirs = ผลผลิต getDirectories (); var files = dielt getFiles (dirs [0]); var contentVal = dielt getContent (ไฟล์ [0]); console.log ('ชื่อไฟล์:', contentval.file); console.log (contentval.content);} function rungenerator () {var gen = run (); ฟังก์ชั่น GO (ผลลัพธ์) {ถ้า (result.done) return; result.value. แล้ว (ฟังก์ชั่น (r) {go (gen.next (r));}); } go (gen.next ());}es7 async/รอ
เครื่องกำเนิดไฟฟ้า ES6 นั้นดีจริงๆ แต่ก็น่าเสียดายที่ฉันต้องการการสนับสนุนจากห้องสมุดบุคคลที่สาม ข่าวดีก็คือ ES 7 จะแนะนำคำหลัก Async/Await เพื่อแก้ปัญหาการโทรแบบอะซิงโครนัสอย่างสมบูรณ์แบบ . NET เป็นหนึ่งก้าวไปข้างหน้าและ. NET Framework 4.5 เป็นคนแรกที่สนับสนุน
รหัสในอนาคตจะถูกเขียนเช่นนี้:
run (); ฟังก์ชั่น async run () {var dirs = รอ getDirectories (); var files = รอ getFiles (dirs [0]); var contentVal = รอ getContent (ไฟล์ [0]); console.log ('ชื่อไฟล์:', contentval.file); console.log (contentval.content);}สรุปแล้ว
จากวิธีการเขียนโปรแกรมแบบอะซิงโครนัสแบบคลาสสิกไปจนถึงการปรับปรุงการเขียนโปรแกรมแบบอะซิงโครนัสโดยข้อมูลจำเพาะของ ES6 Promise จนถึงการประมวลผลที่สง่างามของการรวมตัวกันกับเครื่องกำเนิดไฟฟ้า ES