ปัจจุบันการดำเนินงานแบบอะซิงโครนัสจำนวนมากมีส่วนร่วมในความต้องการและหน้าจริงมีแนวโน้มมากขึ้นในการใช้งานหน้าเดียว ในอนาคตคุณสามารถใช้กระดูกสันหลัง, Angular, Knockout และเฟรมเวิร์กอื่น ๆ แต่ปัญหาของการเขียนโปรแกรมแบบอะซิงโครนัสเป็นปัญหาแรกที่ต้องเผชิญ ด้วยการเพิ่มขึ้นของโหนดการเขียนโปรแกรมแบบอะซิงโครนัสได้กลายเป็นประเด็นที่น่าสนใจมาก หลังจากช่วงเวลาของการเรียนรู้และฝึกฝนรายละเอียดบางอย่างของการเขียนโปรแกรมแบบอะซิงโครนัสได้สรุปไว้
1. การจำแนกประเภทของการเขียนโปรแกรมแบบอะซิงโครนัส
วิธีการแก้ปัญหาแบบอะซิงโครนัสโดยทั่วไปรวมถึง: การโทรกลับโดยตรง, โหมดผับ/ย่อย (โหมดเหตุการณ์), ไลบรารีควบคุมห้องสมุดแบบอะซิงโครนัส (เช่น Async, เมื่อ), สัญญา, เครื่องกำเนิดไฟฟ้า ฯลฯ
1.1 ฟังก์ชั่นการโทรกลับ
ฟังก์ชั่นการโทรกลับมักใช้ในการแก้ปัญหาแบบอะซิงโครนัสซึ่งมักจะสัมผัสและใช้งานง่ายและง่ายต่อการใช้งานในไลบรารีหรือฟังก์ชั่น นี่เป็นวิธีที่ผู้คนมักใช้เมื่อใช้การเขียนโปรแกรมแบบอะซิงโครนัส
อย่างไรก็ตามวิธีฟังก์ชันการโทรกลับมีปัญหาดังต่อไปนี้:
1. อาจมีการสร้างปิรามิดที่ซ้อนกันและรหัสไม่ง่ายที่จะอ่าน
2. ฟังก์ชั่นการโทรกลับเพียงครั้งเดียวเท่านั้นที่สามารถสอดคล้องกันซึ่งกลายเป็นขีด จำกัด ในหลาย ๆ สถานการณ์
1.2 โหมดผับ/ย่อย (เหตุการณ์)
รูปแบบนี้เรียกว่าโหมดเหตุการณ์ซึ่งเป็นเหตุการณ์ของฟังก์ชั่นการโทรกลับและเป็นเรื่องธรรมดามากในไลบรารีคลาสเช่น jQuery
เหตุการณ์ที่เผยแพร่โหมดสมาชิกเองไม่มีปัญหาของการโทรแบบซิงโครนัสและอะซิงโครนัส แต่ในโหนดการเรียกใช้การเรียกใช้ส่วนใหญ่จะถูกเรียกแบบอะซิงโครนัสกับลูปเหตุการณ์ โหมดนี้มักจะใช้เพื่อแยกตรรกะทางธุรกิจ ผู้เผยแพร่เหตุการณ์ไม่จำเป็นต้องให้ความสนใจกับฟังก์ชั่นการโทรกลับที่ลงทะเบียนและพวกเขาไม่จำเป็นต้องให้ความสนใจกับจำนวนฟังก์ชั่นการโทรกลับ ข้อมูลสามารถส่งได้อย่างยืดหยุ่นผ่านข้อความ
ประโยชน์ของรูปแบบนี้คือ: 1. เข้าใจง่าย; 2. ไม่ จำกัด เพียงหนึ่งฟังก์ชันการโทรกลับอีกต่อไป
เมื่อพูดถึงสิ่งเลวร้าย: 1. คุณต้องใช้ไลบรารีคลาส 2. ลำดับเหตุการณ์และฟังก์ชั่นการโทรกลับเป็นสิ่งสำคัญมาก
การคัดลอกรหัสมีดังนี้:
var img = document.QuerySelect (#ID);
img.addeventListener ('โหลด', function () {
// ภาพถูกโหลด
-
-
img.addeventListener ('ข้อผิดพลาด', function () {
// มีบางอย่างผิดปกติ
-
-
มีสองปัญหาเกี่ยวกับรหัสข้างต้น:
. IMG ได้รับการโหลดจริงและฟังก์ชั่นการโทรกลับโหลดถูกผูกไว้ในเวลานี้ เป็นผลให้การโทรกลับจะไม่ถูกดำเนินการ แต่ก็ยังหวังที่จะเรียกใช้ฟังก์ชันการโทรกลับที่เกี่ยวข้อง
การคัดลอกรหัสมีดังนี้:
var img = document.QuerySelect (#ID);
ฟังก์ชันโหลด () {
-
-
ถ้า (img.complete) {
โหลด ();
} อื่น {
img.addeventListener ('โหลด', โหลด);
-
img.addeventListener ('ข้อผิดพลาด', function () {
// มีบางอย่างผิดปกติ
-
-
ข. ไม่สามารถจัดการข้อยกเว้นได้ดี
สรุป: กลไกเหตุการณ์เหมาะสมที่สุดในการจัดการกับเหตุการณ์ซ้ำ ๆ ในวัตถุเดียวกันและไม่จำเป็นต้องพิจารณาเหตุการณ์ก่อนที่ฟังก์ชั่นการโทรกลับจะถูกผูกไว้
1.3 ห้องสมุดควบคุมแบบอะซิงโครนัส
ห้องสมุดอะซิงโครนัสปัจจุบันส่วนใหญ่รวม Q, เมื่อ. js, win.js, rsvp.js ฯลฯ
ลักษณะของไลบรารีเหล่านี้คือรหัสเป็นเส้นตรงและสามารถเขียนได้จากบนลงล่างซึ่งสอดคล้องกับนิสัยธรรมชาติ
สิ่งเลวร้ายก็แตกต่างกันในรูปแบบซึ่งไม่สะดวกในการอ่านและเพิ่มค่าใช้จ่ายในการเรียนรู้
1.4 สัญญา
คำสัญญาถูกแปลเป็นภาษาจีนเป็นสัญญา โดยส่วนตัวแล้วหลังจากเสร็จสิ้นอะซิงโครนัสมันจะให้ผลลัพธ์ภายนอก (ความสำเร็จหรือความล้มเหลว) และสัญญาว่าผลลัพธ์จะไม่เปลี่ยนแปลงอีกต่อไป กล่าวอีกนัยหนึ่งสัญญาสะท้อนถึงค่าผลตอบแทนสุดท้ายของการดำเนินการ (สัญญาแสดงถึงค่าในที่สุดที่ส่งคืนจากการดำเนินการครั้งเดียว) ในปัจจุบันสัญญาได้รับการแนะนำให้รู้จักกับข้อกำหนด ES6 และเบราว์เซอร์ขั้นสูงเช่น Chrome และ Firefox ได้ใช้วิธีการดั้งเดิมนี้ภายในซึ่งค่อนข้างสะดวกในการใช้งาน
ต่อไปนี้เป็นลักษณะของสัญญาจากด้านต่อไปนี้:
1.4.1 สถานะ
มันมีสามรัฐ: รอดำเนินการและปฏิเสธ ทั้งสามรัฐสามารถผ่านการเปลี่ยนแปลงได้สองครั้ง (จากรอดำเนินการ ---> สำเร็จ, รอดำเนินการ-> ถูกปฏิเสธ) และการเปลี่ยนแปลงของรัฐสามารถเกิดขึ้นได้เพียงครั้งเดียว
1.4.2 จากนั้นวิธีการ
วิธีการนั้นใช้เพื่อระบุฟังก์ชั่นการโทรกลับหลังจากเหตุการณ์แบบอะซิงโครนัสเสร็จสมบูรณ์
วิธีนี้สามารถกล่าวได้ว่าเป็นวิธีการของคำสัญญาซึ่งทำให้สัญญาเต็มไปด้วยเวทมนตร์ มีอาการเฉพาะหลายอย่างดังนี้:
a) วิธีการส่งคืนสัญญา สิ่งนี้ช่วยให้การดำเนินงานแบบอนุกรมของการดำเนินการแบบอะซิงโครนัสหลายครั้ง
เกี่ยวกับวงกลมสีเหลือง 1 ในรูปด้านบนการประมวลผลของมูลค่าเป็นส่วนที่ซับซ้อนกว่าของสัญญา การประมวลผลของมูลค่าแบ่งออกเป็นสองสถานการณ์: วัตถุสัญญาและวัตถุที่ไม่ใช่การประนีประนอม
เมื่อค่าไม่ใช่ประเภทสัญญาเพียงใช้ค่าเป็นค่าพารามิเตอร์ของการแก้ไขของสัญญาที่สอง; เมื่อมันเป็นประเภทสัญญาสถานะและพารามิเตอร์ของ Promise2 จะถูกกำหนดโดยค่าอย่างสมบูรณ์ ถือได้ว่า Promsie2 เป็นหุ่นเชิดที่มีค่าและ Promise2 เป็นเพียงสะพานเชื่อมต่อแบบอะซิงโครนัสที่แตกต่างกัน
การคัดลอกรหัสมีดังนี้:
Promise.prototype.then = function (onfulfilled, onrejected) {
ส่งคืนสัญญาใหม่ (ฟังก์ชั่น (แก้ไข, ปฏิเสธ) {// สัญญาที่นี่ถูกทำเครื่องหมายว่าเป็นสัญญา 2
รับมือ({
onfulfilled: onfullilled,
onrejected: onrejected,
แก้ไข: แก้ไข
ปฏิเสธ: ปฏิเสธ
-
-
-
มือจับฟังก์ชั่น (รอการตัดบัญชี) {
var handlefn;
if (state === 'เติมเต็ม') {
handlefn = deverred.onfulfilled;
} อื่นถ้า (state === 'ปฏิเสธ') {
handlefn = deverred.onrejected;
-
var ret = handlefn (ค่า);
referred.resolve (ret); // โปรดทราบว่าการแก้ไขในเวลานี้คือการแก้ไข Promise2
-
ฟังก์ชั่นแก้ไข (val) {
if (val && typeof val.then === 'function') {
วาลแล้ว (แก้ไข); // ถ้า Val เป็นวัตถุสัญญาหรือวัตถุสัญญาชั้นเรียนสถานะของ Promise2 จะถูกกำหนดโดย VAL อย่างสมบูรณ์
กลับ;
-
if (callback) {// callback เป็นฟังก์ชันการโทรกลับที่ระบุ
การโทรกลับ (วาล);
-
-
b) การแปลงระหว่างไลบรารีอะซิงโครนัสที่แตกต่างกันหลายรายการถูกนำมาใช้
มีวัตถุที่เรียกว่าในอะซิงโครนัสซึ่งหมายถึงวัตถุที่มีวิธีการนั้น ตราบใดที่วัตถุวัตถุมีวิธีการนั้นก็สามารถแปลงได้เช่น:
การคัดลอกรหัสมีดังนี้:
var referred = $ ('aa.ajax'); // !! รอการตัดบัญชีแล้ว === จริง
var p = pression.resolve (รอการตัดบัญชี);
P. แล้ว (...... )
1.4.3 CommonJS Promise/A Specification
ปัจจุบันมีสัญญา/A และ Promise/A+ ข้อมูลจำเพาะสำหรับข้อกำหนดเกี่ยวกับสัญญาซึ่งแสดงให้เห็นว่าการดำเนินการตามสัญญาค่อนข้างซับซ้อน
การคัดลอกรหัสมีดังนี้:
จากนั้น (fomendilledhandler, ปฏิเสธ handler, progresshandler)
1.4.4 หมายเหตุ
ฟังก์ชั่นการโทรกลับในสัญญาแบ่งปันค่า ในการประมวลผลผลลัพธ์ค่าจะถูกส่งผ่านเป็นพารามิเตอร์ไปยังฟังก์ชันการโทรกลับที่สอดคล้องกัน หากค่าเป็นวัตถุให้ระวังอย่าแก้ไขค่าได้อย่างง่ายดาย
การคัดลอกรหัสมีดังนี้:
var p = promise.resolve ({x: 1});
P.then (ฟังก์ชั่น (val) {
console.log ('การโทรกลับครั้งแรก:'+val.x ++);
-
P.then (ฟังก์ชั่น (val) {
console.log ('การโทรกลับครั้งที่สอง:' + val.x)
-
// การโทรกลับครั้งแรก: 1
// การโทรกลับครั้งที่สอง: 2
1.5 เครื่องกำเนิดไฟฟ้า
วิธีการทั้งหมดข้างต้นจะขึ้นอยู่กับฟังก์ชั่นการโทรกลับเพื่อให้การดำเนินการแบบอะซิงโครนัสเสร็จสมบูรณ์และไม่มีอะไรมากไปกว่าการห่อหุ้มฟังก์ชั่นการโทรกลับ ES6 เสนอเครื่องกำเนิดไฟฟ้าซึ่งเพิ่มวิธีในการแก้ปัญหาการทำงานแบบอะซิงโครนัสและไม่เสร็จสมบูรณ์ตามฟังก์ชั่นการโทรกลับอีกต่อไป
คุณสมบัติที่ใหญ่ที่สุดของเครื่องกำเนิดไฟฟ้าคือมันสามารถหยุดและรีสตาร์ทฟังก์ชั่นซึ่งเอื้อต่อการแก้ปัญหาการทำงานแบบอะซิงโครนัส การรวมการหยุดชั่วคราวของเครื่องกำเนิดไฟฟ้าเข้ากับการจัดการข้อยกเว้นของสัญญาสามารถแก้ปัญหาการเขียนโปรแกรมแบบอะซิงโครนัสได้อย่างสง่างามยิ่งขึ้น การอ้างอิงการใช้งานเฉพาะ: Kyle Simpson
2. ปัญหาเกี่ยวกับการเขียนโปรแกรมแบบอะซิงโครนัส
2.1 การจัดการข้อยกเว้น
A) เหตุการณ์แบบอะซิงโครนัสรวมถึงสองลิงก์: การออกคำขอแบบอะซิงโครนัสและผลการประมวลผล ลิงก์ทั้งสองนี้เชื่อมต่อผ่านลูปเหตุการณ์ จากนั้นเมื่อลองจับเพื่อทำการจับข้อยกเว้นคุณต้องจับมัน
การคัดลอกรหัสมีดังนี้:
พยายาม {
Asyncevent (โทรกลับ);
} catch (err) {
-
-
รหัสข้างต้นไม่สามารถจับข้อยกเว้นในการโทรกลับและสามารถรับข้อยกเว้นในกระบวนการร้องขอเท่านั้น ปัญหานี้มีปัญหา: หากการออกคำขอและการประมวลผลคำขอเสร็จสมบูรณ์โดยคนสองคนแล้วมีปัญหาเมื่อจัดการข้อยกเว้น?
b) สัญญาใช้การส่งมอบข้อยกเว้นซึ่งนำผลประโยชน์บางอย่างมาเพื่อให้แน่ใจว่ารหัสไม่ได้ถูกบล็อกในโครงการจริง อย่างไรก็ตามหากมีเหตุการณ์แบบอะซิงโครนัสจำนวนมากมันไม่ง่ายเลยที่จะค้นหาว่าเหตุการณ์แบบอะซิงโครนัสใดที่สร้างข้อยกเว้น
การคัดลอกรหัสมีดังนี้:
// คำอธิบายฉาก: แสดงข้อมูลสัญญาณเตือนราคาใน CRM รวมถึงข้อมูลการแข่งขัน อย่างไรก็ตามใช้เวลานานกว่าจะได้รับข้อมูลการแข่งขัน เพื่อหลีกเลี่ยงการสืบค้นช้าแบ็กเอนด์จะแยกบันทึกออกเป็นสองชิ้นเพื่อให้ได้มันแยกกัน
// ขั้นตอนที่ 1: รับข้อมูลสัญญาณเตือนราคานอกเหนือจากข้อมูลการแข่งขัน
ฟังก์ชั่น getPriceAlarmData () {
ส่งคืนสัญญาใหม่ (ฟังก์ชั่น (แก้ไข) {
y.io (url, {
วิธี: 'รับ',
ข้อมูล: params,
บน: function () {
ความสำเร็จ: ฟังก์ชั่น (id, data) {
แก้ไข (AlarmData);
-
-
-
-
-
// หลังจากได้รับข้อมูลการเตือนแล้วไปที่ข้อมูลการแข่งขัน
getPriceAlarmData () จากนั้น (ฟังก์ชั่น (ข้อมูล) {
// การแสดงผลข้อมูลนอกเหนือจากข้อมูลการแข่งขัน
render (ข้อมูล);
ส่งคืนสัญญาใหม่ (ฟังก์ชั่น (แก้ไข) {
y.io (url, {
วิธี: 'รับ',
ข้อมูล: {AlarmList: Data},
บน: function () {
ความสำเร็จ: ฟังก์ชั่น (id, compdata) {
แก้ไข (compdata);
-
-
-
-
}) // หลังจากได้รับข้อมูลทั้งหมดแล้วการแสดงผลข้อมูลการแข่งขัน
. แล้ว (ฟังก์ชั่น (ข้อมูล) {
// แสดงข้อมูลการเสนอราคา
Render (ข้อมูล)
}, ฟังก์ชัน (err) {
// การจัดการข้อยกเว้น
console.log (err);
-
รหัสข้างต้นสามารถแปลงเป็นดังต่อไปนี้:
การคัดลอกรหัสมีดังนี้:
พยายาม{
// รับข้อมูลการเตือนภัยนอกเหนือจากการแข่งขัน
var AlarmData = AlarmDataExceptCompare ();
Render (AlarmData);
// การสอบถามข้อมูลการแข่งขันตามข้อมูลการเตือนภัย
var เปรียบเทียบ = getCompareInfo (AlarmData);
เรนเดอร์ (เปรียบเทียบ);
} catch (err) {
console.log (err.message);
-
ในตัวอย่างข้างต้นข้อยกเว้นจะถูกจัดการในตอนท้ายดังนั้นเมื่อมีข้อยกเว้นเกิดขึ้นในลิงค์บางอย่างเราไม่สามารถรู้ได้อย่างชัดเจนว่าเหตุการณ์ใดที่ถูกสร้างขึ้น
2.2 jQuery.deverred ปัญหา
การดำเนินการแบบอะซิงโครนัสยังถูกนำไปใช้ใน jQuery แต่พวกเขาไม่ปฏิบัติตามคำสัญญา/A+ ข้อกำหนดในการดำเนินการและส่วนใหญ่สะท้อนให้เห็นในด้านต่อไปนี้:
. จำนวนพารามิเตอร์: สัญญามาตรฐานสามารถยอมรับพารามิเตอร์เดียวเท่านั้นในขณะที่ jQuery สามารถผ่านพารามิเตอร์หลายตัว
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น asyncinjQuery () {
var d = ใหม่ $ .deverred ();
settimeout (function () {
d.resolve (1, 2);
}, 100);
ส่งคืน d.promise ()
-
asyncinjQuery (). จากนั้น (ฟังก์ชั่น (val1, val2) {
console.log ('เอาต์พุต:', val1, val2);
-
// เอาท์พุท: 1 2
ข. การจัดการข้อยกเว้นในการประมวลผลผลลัพธ์
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น asyncinpromise () {
ส่งคืนสัญญาใหม่ (ฟังก์ชั่น (แก้ไข) {
settimeout (function () {
var jsonstr = '{"ชื่อ": "mt}';
แก้ไข (jsonstr);
}, 100);
-
-
asyncinpromise (). จากนั้น (ฟังก์ชั่น (val) {
var d = json.parse (val);
console.log (d.name);
}) แล้ว (NULL, ฟังก์ชั่น (ERR) {
console.log ('แสดงข้อผิดพลาด:' + err.message);
-
// แสดงข้อผิดพลาด: สิ้นสุดอินพุตที่ไม่คาดคิด
ฟังก์ชั่น asyncinjQuery () {
var d = ใหม่ $ .deverred ();
settimeout (function () {
var jsonstr = '{"ชื่อ": "mt}';
D.Resolve (JSONSTR);
}, 100);
ส่งคืน d.promise ()
-
asyncinjQuery (). จากนั้น (ฟังก์ชั่น (val) {
var d = json.parse (val);
console.log (d.name);
}). จากนั้น (ฟังก์ชั่น (v) {
console.log ('ความสำเร็จ:', v.name);
}, ฟังก์ชัน (err) {
console.log ('แสดงข้อผิดพลาด:' + err.message);
-
// uncaught syntaxerror: สิ้นสุดการป้อนข้อมูลที่ไม่คาดคิด
จะเห็นได้จากสิ่งนี้ที่สัญญาประมวลผลผลลัพธ์ของฟังก์ชั่นการโทรกลับซึ่งสามารถจับข้อยกเว้นในระหว่างการดำเนินการของฟังก์ชันการโทรกลับ แต่ jQuery.deverred ไม่สามารถทำได้