1. บทบาทของ node.js
ความหมายของ I/O, (I/O คือตัวย่อของอินพุต/เอาต์พุตเช่น: ข้อความประเภทแป้นพิมพ์อินพุตและข้อความจะปรากฏขึ้นบนหน้าจอการเคลื่อนที่ของเมาส์เมาส์จะถูกย้ายเมาส์จะถูกย้ายบนหน้าจออินพุตเทอร์มินัลและเอาต์พุตที่เห็น ฯลฯ )
ปัญหาที่ Node.js ต้องการแก้ไข (อินพุตประมวลผลการเกิดขึ้นพร้อมกันสูงตัวอย่างเช่นอาจมีนักเล่นเกมหลายล้านคนในเกมออนไลน์และอินพุตหลายล้านรายการ ฯลฯ ) (node.js เหมาะสำหรับหมวดหมู่: Node.js เหมาะสมที่สุดเมื่อแอปพลิเคชันต้องการส่งและรับข้อมูลบนเครือข่าย
ความหมายของการเกิดขึ้นพร้อมกัน (คำศัพท์พร้อมกันอธิบายว่าสิ่งต่าง ๆ จะเกิดขึ้นในเวลาเดียวกันและอาจโต้ตอบกันโมเดล I/O เหตุการณ์ของโหนดช่วยให้เราสามารถหลีกเลี่ยงปัญหาทั่วไปของการประสานและการเกิดขึ้นพร้อมกัน
เครือข่ายสาธิต I/O
รหัส JS
var http = ต้องการ ('http'), urls = ['www.baidu.com', 'www.10jqka.com.cn', 'www.duokan.com']; ฟังก์ชั่น fetchPage (url) {var start = new date (); http.get ({โฮสต์: url}, ฟังก์ชั่น (res) {console.log ("ได้รับการตอบกลับจาก:" + url); console.log ("คำขอ:", วันที่ใหม่ () - เริ่ม "MS");}); } สำหรับ (var i = 0; i <urls.length; i ++) {fetchPage (urls [i]); -ชื่อ node.js
เราเรียกใช้โหนดโหนด. js ในเทอร์มินัล
เอาท์พุท:
เราต้องการ node.js เพื่อเข้าถึง URL สาม URL และรายงานการตอบสนองที่ได้รับและเวลาที่ใช้
เราจะเห็นได้ว่าเวลาส่งออกจะแตกต่างกันไปสองครั้ง ได้รับผลกระทบจากปัจจัยต่าง ๆ เวลาในการแก้ไขคำขอ DNS โปรแกรมเซิร์ฟเวอร์ไม่ว่าง ฯลฯ
เหตุใด JavaScript จึงเป็นภาษาที่ขับเคลื่อนด้วยเหตุการณ์
JavaScript หมุนรอบสถาปัตยกรรมเหตุการณ์ที่เชื่อมโยงกับโมเดลวัตถุเอกสาร (DOM) นักพัฒนาสามารถทำสิ่งต่าง ๆ เมื่อเหตุการณ์เกิดขึ้น เหตุการณ์เหล่านี้รวมถึงผู้ใช้คลิกที่องค์ประกอบหน้าเสร็จสมบูรณ์ ฯลฯ โดยใช้กิจกรรมนักพัฒนาสามารถเขียนผู้ฟังสำหรับเหตุการณ์ที่เกิดขึ้นเมื่อเหตุการณ์เกิดขึ้น
2. โทรกลับ
1. การโทรกลับคืออะไร
2. วิเคราะห์การโทรกลับ
การเรียกกลับหมายถึงการส่งฟังก์ชั่นเป็นอาร์กิวเมนต์ไปยังฟังก์ชั่นอื่นและมักจะเรียกว่าหลังจากฟังก์ชั่นแรกเสร็จสมบูรณ์
ตัวอย่าง: ตัวอย่างวิธีการซ่อน () ใน jQuery
รหัส JS
1, $ ("P") ซ่อน ('ช้า'); 2, $ ("p"). ซ่อน ('ช้า', ฟังก์ชัน () {แจ้งเตือน ("ย่อหน้าตอนนี้ซ่อนอยู่")});การโทรกลับเป็นทางเลือก
1 ไม่จำเป็นต้องโทรกลับ
2. มีการโทรกลับ เมื่อย่อหน้าถูกซ่อนมันจะถูกเรียกว่าแสดงพร้อมแจ้งเตือน
เพื่อดูความแตกต่างระหว่างรหัสที่มีและไม่มีการโทรกลับ
รหัส JS
$ ("p"). ซ่อน ('ช้า'); การแจ้งเตือน ("ย่อหน้าตอนนี้ซ่อนอยู่"); // 1 $ ("P"). ซ่อน ('ช้า' ฟังก์ชั่น () {แจ้งเตือน ("ย่อหน้าตอนนี้ซ่อนอยู่")}); // 21. ไม่มีการโทรกลับและลำดับการดำเนินการเหมือนกัน อย่างไรก็ตามเราจะเห็นได้ว่าย่อหน้า P ไม่ได้ถูกซ่อนไว้อย่างสมบูรณ์การแจ้งเตือนออกมา
2. มีการโทรกลับและการดำเนินการจะเสร็จสิ้นหลังจากที่ซ่อนเสร็จ
วิเคราะห์การโทรกลับ
รหัส JS
ฟังก์ชั่น havebreakfast (อาหาร, เครื่องดื่ม, การโทรกลับ) {console.log ('มี barakfast ของ' + อาหาร + ',' + เครื่องดื่ม); if (callback && typeof (callback) === "function") {callback (); }} hasbreakfast ('foast', 'กาแฟ', function () {console.log ('เสร็จอาหารเช้าเสร็จเวลาไปทำงาน!');});เอาท์พุท:
มี Barakfast of Foam อาหารเช้าที่ทำด้วยกาแฟ ถึงเวลาไปทำงาน!
นี่คือฟังก์ชั่นที่สร้างขึ้นด้วยพารามิเตอร์สามตัวพารามิเตอร์ที่สามคือการเรียกกลับซึ่งจะต้องเป็นฟังก์ชัน
ฟังก์ชั่น Hasbreakfast บันทึกสิ่งที่คุณกินลงในคอนโซลแล้วเรียกใช้ฟังก์ชันการโทรกลับที่ส่งผ่านเป็นพารามิเตอร์
วิธีใช้การโทรกลับสำหรับ node.js
ตัวอย่างการใช้โมดูลระบบไฟล์เพื่ออ่านเนื้อหาไฟล์จากดิสก์ใน node.js
รหัส JS
var fs = ต้องการ ('fs'); fs.readfile ('somefile.txt', 'utf8', ฟังก์ชั่น (err, data) {ถ้า (err) throw err; console.log (data);});ผลลัพธ์คือ: เนื้อหาใน somefile.txt
1. โมดูล FS (ระบบไฟล์) ขอให้ใช้ในสคริปต์
2. พา ธ ไฟล์บนระบบไฟล์มีให้เป็นพารามิเตอร์แรกไปยังวิธี Fs.ReadFile
3. พารามิเตอร์ที่สองคือ UTF8 ซึ่งระบุการเข้ารหัสของไฟล์
4. ระบุฟังก์ชั่นการเรียกกลับเป็นพารามิเตอร์ที่สามไปยังวิธี fs.readfile
5. พารามิเตอร์แรกของฟังก์ชั่นการเรียกกลับเป็น ERR ซึ่งใช้เพื่อบันทึกข้อผิดพลาดที่ส่งคืนเมื่ออ่านไฟล์
6. พารามิเตอร์ที่สองของฟังก์ชั่นการโทรกลับคือการกดปุ่มและผู้ใช้จะบันทึกข้อมูลที่ส่งคืนโดยไฟล์อ่าน
7. เมื่ออ่านไฟล์แล้วการโทรกลับจะถูกเรียก
8. หาก ERR เป็นจริงข้อผิดพลาดจะถูกโยนลงไป
9. หาก ERR เป็นเท็จคุณสามารถใช้ข้อมูลจากไฟล์ได้
10. ในกรณีนี้ข้อมูลจะถูกบันทึกไว้ในคอนโซล
อีกอันหนึ่งคือโมดูล HTTP โมดูล HTTP ช่วยให้นักพัฒนาสามารถสร้างไคลเอนต์และเซิร์ฟเวอร์ HTTP
รหัส JS
var http = ต้องการ ('http'); http.get ({host: 'shapeshed.com'}, ฟังก์ชั่น (res) {console.log ("ได้รับการตอบกลับ:" + res.statuscode);}). on ('ข้อผิดพลาด', ฟังก์ชัน (e) {console.log ("มีข้อผิดพลาด:" + e.message);});ผลลัพธ์: ได้รับการตอบกลับ: 200
1. ขอโมดูล HTTP สำหรับใช้ในสคริปต์
2. ระบุสองพารามิเตอร์ไปยังวิธี http.get ()
3. พารามิเตอร์แรกคือวัตถุตัวเลือก ในตัวอย่างนี้คุณต้องได้รับหน้าแรกของ shapeshed.com
4. พารามิเตอร์ที่สองเป็นฟังก์ชันการเรียกกลับพร้อมการตอบสนองเป็นพารามิเตอร์
5. เมื่อเซิร์ฟเวอร์ระยะไกลส่งคืนฟังก์ชั่นที่เกี่ยวข้องฟังก์ชันการโทรกลับจะถูกเรียกใช้
6. บันทึกรหัสสถานะการตอบกลับในฟังก์ชันการโทรกลับ หากมีข้อผิดพลาดใด ๆ คุณสามารถบันทึกได้
ต่อไปมาดูกันว่าการดำเนินการ I/O ที่แตกต่างกัน 4 ครั้งกำลังเกิดขึ้นพวกเขาทั้งหมดใช้การโทรกลับ
รหัส JS
var fs = ต้องการ ('fs'), http = ต้องการ ('http'); http.get ({host: 'www.baidu.com'}, ฟังก์ชั่น (res) {console.log ("baidu.com");}). on ('ข้อผิดพลาด', ฟังก์ชั่น (e) {console.log ("มีข้อผิดพลาด:" + e.message);}); fs.readfile ('somefile.txt', 'utf8', ฟังก์ชั่น (err, data) {ถ้า (err) โยน err; console.log ("somefile");}); http.get ({host: 'www.duokan.com'}, ฟังก์ชั่น (res) {console.log ("duokan.com");}). on ('ข้อผิดพลาด', ฟังก์ชั่น (e) {console.log ("มีข้อผิดพลาด:" + e.message);}); fs.readfile ('somefile2.txt', 'utf8', ฟังก์ชั่น (err, data) {ถ้า (err) โยน err; console.log ("somefile2");});เราจะรู้ได้ไหมว่าการดำเนินการใดที่กลับมาก่อน
การเดาคือไฟล์ทั้งสองที่อ่านจากดิสก์จะถูกส่งคืนก่อนเพราะไม่จำเป็นต้องป้อนเครือข่าย แต่มันยากสำหรับเราที่จะบอกว่าไฟล์ใดจะกลับมาก่อนเพราะเราไม่ทราบขนาดไฟล์ สำหรับการได้มาซึ่งหน้าแรกสองหน้าสคริปต์จำเป็นต้องเข้าสู่เครือข่ายและเวลาตอบสนองขึ้นอยู่กับสิ่งที่คาดเดาไม่ได้มากมาย กระบวนการ Node.js จะไม่ออกจนกว่าจะมีการโทรกลับที่ลงทะเบียนซึ่งไม่ได้ถูกเรียกใช้ การโทรกลับเป็นครั้งแรกแก้ปัญหาที่คาดเดาไม่ได้และเป็นวิธีที่มีประสิทธิภาพในการจัดการกับการเกิดขึ้นพร้อมกัน (หรือทำมากกว่าหนึ่งครั้งในแต่ละครั้ง)
นี่คือผลลัพธ์ของการดำเนินการของฉัน
รหัสแบบซิงโครนัสและอะซิงโครนัส
ก่อนอื่นดูรหัสซิงโครไนซ์ (หรือบล็อก) รหัส
รหัส JS
ฟังก์ชั่นนอนหลับ (มิลลิวินาที) {var start = new date (). getTime (); ในขณะที่ ((วันที่ใหม่ (). getTime () -Start) <หลายล้านรายการ) {}} function fetchPage () {console.log ('การดึงหน้า'); การนอนหลับ (2000); console.log ('ส่งคืนข้อมูลจากหน้าร้องขอ'); } ฟังก์ชั่น fetchapi () {console.log ('การดึง API'); การนอนหลับ (2000); console.log ('ข้อมูลส่งคืนจาก API'); } fetchPage (); fetchapi ();เมื่อสคริปต์กำลังทำงานฟังก์ชั่น fetchPage () จะถูกเรียก จนกว่าจะกลับมาการทำงานของสคริปต์จะถูกบล็อก ก่อนที่ฟังก์ชั่น fetchPage () จะส่งคืนโปรแกรมไม่สามารถย้ายไปยังฟังก์ชัน fetchapi () สิ่งนี้เรียกว่าการปิดกั้น
node.js แทบจะไม่เคยใช้รูปแบบการเข้ารหัสนี้ แต่เรียกการเรียกกลับแบบอะซิงโครนัส
ดูรหัสต่อไปนี้
รหัส JS
var http = ต้องการ ('http'); function fetchPage () {console.log ('การดึงหน้า'); http.get ({โฮสต์: 'www.baidu.com', เส้นทาง: '/? delay = 2000'}, ฟังก์ชั่น (res) {console.log ('ข้อมูลที่ส่งคืนจากการร้องขอหน้า');}) on ('ข้อผิดพลาด', ฟังก์ชั่น (e) {console.log ("มีข้อผิดพลาด" + e); } ฟังก์ชั่น fetchapi () {console.log ('การดึง API'); http.get ({โฮสต์: 'www.baidu.com', เส้นทาง: '/? delay = 2000'}, ฟังก์ชั่น (res) {console.log ('ข้อมูลที่ส่งคืนจากการร้องขอ api');}) on ('ข้อผิดพลาด', ฟังก์ชั่น (e) {console.log ("มีข้อผิดพลาด" + e); } fetchPage (); fetchapi ();เมื่อรหัสนี้ได้รับอนุญาตคุณจะไม่รอฟังก์ชั่น fetchPage () อีกต่อไปและฟังก์ชัน fetchapi () จะถูกเรียกทันที รหัสถูกบล็อกโดยใช้การโทรกลับ เมื่อเรียกว่าทั้งสองฟังก์ชั่นฟังการกลับมาของเซิร์ฟเวอร์ระยะไกลและเรียกใช้ฟังก์ชันการโทรกลับ
โปรดทราบว่าไม่สามารถรับประกันคำสั่งส่งคืนของฟังก์ชั่นเหล่านี้ได้ แต่เกี่ยวข้องกับเครือข่าย
ลูปเหตุการณ์
node.js ใช้ลูปเหตุการณ์ของ JavaScript เพื่อรองรับสไตล์การเขียนโปรแกรมแบบอะซิงโครนัสที่สนับสนุน โดยทั่วไปลูปเหตุการณ์อนุญาตให้ระบบบันทึกฟังก์ชั่นการโทรกลับก่อนจากนั้นเรียกใช้เมื่อเหตุการณ์เกิดขึ้นในอนาคต นี่อาจเป็นข้อมูลการส่งคืนฐานข้อมูลหรือข้อมูลการส่งคืนคำขอ HTTP เนื่องจากการดำเนินการของฟังก์ชั่นการโทรกลับถูกเลื่อนออกไปจนกว่าเหตุการณ์จะถูกย้อนกลับจึงไม่จำเป็นต้องหยุดการดำเนินการและกระแสควบคุมสามารถกลับไปที่สภาพแวดล้อมของโหนดรันไทม์ทำให้สิ่งอื่น ๆ เกิดขึ้น
Node.js มักถูกมองว่าเป็นกรอบการเขียนโปรแกรมเครือข่ายเนื่องจากได้รับการออกแบบมาเพื่อจัดการกับความไม่แน่นอนในการไหลของข้อมูลในเครือข่าย สิ่งที่ก่อให้เกิดการออกแบบดังกล่าวคือลูปเหตุการณ์และการใช้การโทรกลับและพวกเขาก็เหมือนโปรแกรมเมอร์ที่สามารถเขียนรหัสแบบอะซิงโครนัสที่ตอบสนองต่อเหตุการณ์เครือข่ายหรือ I/O
กฎที่จะปฏิบัติตามคือ: ฟังก์ชั่นจะต้องกลับมาอย่างรวดเร็วฟังก์ชั่นจะต้องไม่ถูกบล็อกและการดำเนินการที่ดำเนินมายาวนานจะต้องถูกย้ายไปยังกระบวนการอื่น
สิ่งที่ไม่เหมาะสำหรับ Node.js รวมถึงการประมวลผลข้อมูลจำนวนมากหรือการคำนวณการใช้งานเป็นเวลานาน Node.js ได้รับการออกแบบมาเพื่อผลักดันข้อมูลบนเครือข่ายและทำให้เสร็จสมบูรณ์ทันที