10 ข้อผิดพลาดที่พบบ่อยที่สุดที่นักพัฒนา Node.js สร้าง
เผยแพร่แล้ว: 2022-03-11นับตั้งแต่วินาทีที่ Node.js ถูกเปิดเผยสู่สายตาชาวโลก ก็ได้รับการชื่นชมและวิจารณ์อย่างยุติธรรม การอภิปรายยังคงดำเนินต่อไป และอาจไม่สิ้นสุดในเร็วๆ นี้ สิ่งที่เรามักมองข้ามในการโต้วาทีเหล่านี้คือทุกภาษาการเขียนโปรแกรมและแพลตฟอร์มถูกวิพากษ์วิจารณ์โดยอิงจากปัญหาบางอย่าง ซึ่งสร้างขึ้นโดยวิธีที่เราใช้แพลตฟอร์ม ไม่ว่า Node.js จะทำให้การเขียนโค้ดปลอดภัยยากเพียงใด และความง่ายในการเขียนโค้ดพร้อมกันอย่างมาก แพลตฟอร์มนี้มีมาระยะหนึ่งแล้วและมีการใช้เพื่อสร้างบริการเว็บที่มีประสิทธิภาพและซับซ้อนจำนวนมาก บริการเว็บเหล่านี้ปรับขนาดได้ดีและได้พิสูจน์ความเสถียรผ่านความอดทนของเวลาบนอินเทอร์เน็ต
อย่างไรก็ตาม เช่นเดียวกับแพลตฟอร์มอื่นๆ Node.js มีความเสี่ยงต่อปัญหาและปัญหาของนักพัฒนา ข้อผิดพลาดบางประการเหล่านี้ทำให้ประสิทธิภาพลดลง ในขณะที่ข้อผิดพลาดอื่นๆ ทำให้ Node.js ดูเหมือนใช้ไม่ได้กับสิ่งที่คุณพยายามทำให้สำเร็จ ในบทความนี้ เราจะมาดูข้อผิดพลาดทั่วไป 10 ข้อที่นักพัฒนาซอฟต์แวร์เพิ่งเริ่มใช้ Node.js มักทำ และวิธีหลีกเลี่ยงข้อผิดพลาดเหล่านี้ในการเป็น Node.js pro
ข้อผิดพลาด #1: การบล็อกการวนซ้ำของเหตุการณ์
JavaScript ใน Node.js (เหมือนกับในเบราว์เซอร์) ให้สภาพแวดล้อมแบบเธรดเดียว ซึ่งหมายความว่าไม่มีสองส่วนของแอปพลิเคชันของคุณทำงานแบบขนาน การทำงานพร้อมกันทำได้โดยการจัดการการดำเนินการที่ผูกไว้กับ I/O แบบอะซิงโครนัสแทน ตัวอย่างเช่น คำขอจาก Node.js ไปยังเอ็นจิ้นฐานข้อมูลเพื่อดึงเอกสารบางอย่างทำให้ Node.js สามารถโฟกัสไปที่ส่วนอื่นของแอปพลิเคชันได้:
// Trying to fetch an user object from the database. Node.js is free to run other parts of the code from the moment this function is invoked.. db.User.get(userId, function(err, user) { // .. until the moment the user object has been retrieved here })
อย่างไรก็ตาม โค้ดที่ผูกกับ CPU ในอินสแตนซ์ Node.js ที่มีไคลเอ็นต์นับพันเชื่อมต่ออยู่ ก็ใช้เพื่อบล็อกการวนซ้ำของเหตุการณ์ ซึ่งทำให้ไคลเอ็นต์ทั้งหมดรอ รหัสที่ผูกกับ CPU รวมถึงการพยายามจัดเรียงอาร์เรย์ขนาดใหญ่ การเรียกใช้การวนซ้ำที่ยาวมาก และอื่นๆ ตัวอย่างเช่น:
function sortUsersByAge(users) { users.sort(function(a, b) { return a.age < b.age ? -1 : 1 }) }
การเรียกใช้ฟังก์ชัน "sortUsersByAge" นี้อาจใช้ได้หากเรียกใช้ในอาร์เรย์ "ผู้ใช้" ขนาดเล็ก แต่ด้วยอาร์เรย์ขนาดใหญ่ จะมีผลกระทบร้ายแรงต่อประสิทธิภาพโดยรวม หากเป็นสิ่งที่ต้องทำอย่างแน่นอน และคุณแน่ใจว่าจะไม่มีอะไรรออีกในลูปของเหตุการณ์ (เช่น หากนี่เป็นส่วนหนึ่งของเครื่องมือบรรทัดคำสั่งที่คุณกำลังสร้างด้วย Node.js และมัน ไม่สำคัญหรอกว่าสิ่งทั้งหมดจะทำงานพร้อมกัน) นี่อาจไม่ใช่ปัญหา อย่างไรก็ตาม ในอินสแตนซ์ของเซิร์ฟเวอร์ Node.js ที่พยายามให้บริการผู้ใช้หลายพันคนในแต่ละครั้ง รูปแบบดังกล่าวสามารถพิสูจน์ได้ว่าร้ายแรง
หากอาร์เรย์ของผู้ใช้นี้ถูกดึงมาจากฐานข้อมูล ทางออกที่ดีคือการดึงข้อมูลซึ่งจัดเรียงไว้แล้วโดยตรงจากฐานข้อมูล หากวนรอบเหตุการณ์ถูกบล็อกโดยลูปที่เขียนขึ้นเพื่อคำนวณผลรวมของข้อมูลธุรกรรมทางการเงินที่มีประวัติอันยาวนาน อาจถูกเลื่อนไปยังการตั้งค่าของผู้ปฏิบัติงานภายนอก/คิวเพื่อหลีกเลี่ยงการวนรอบเหตุการณ์
อย่างที่คุณเห็น ไม่มีวิธีแก้ปัญหา Silver-bullet สำหรับปัญหา Node.js ประเภทนี้ แต่แต่ละกรณีจะต้องได้รับการแก้ไขเป็นรายบุคคล แนวคิดพื้นฐานคือการไม่ใช้งาน CPU ที่เข้มข้นภายในอินสแตนซ์ Node.js ที่หันหน้าเข้าหากัน ซึ่งเป็นสิ่งที่ไคลเอ็นต์เชื่อมต่อพร้อมกัน
ข้อผิดพลาด #2: เรียกใช้การโทรกลับมากกว่าหนึ่งครั้ง
JavaScript อาศัยการโทรกลับตั้งแต่ตลอดไป ในเว็บเบราว์เซอร์ เหตุการณ์จะได้รับการจัดการโดยส่งการอ้างอิงไปยังฟังก์ชัน (มักจะไม่ระบุตัวตน) ที่ทำหน้าที่เหมือนการเรียกกลับ ใน Node.js การเรียกกลับเป็นวิธีเดียวที่องค์ประกอบอะซิงโครนัสของโค้ดของคุณสื่อสารกัน จนกระทั่งมีการแนะนำคำสัญญา การโทรกลับยังคงใช้งานอยู่ และผู้พัฒนาแพ็คเกจยังคงออกแบบ API ของตนเกี่ยวกับการเรียกกลับ ปัญหาทั่วไปของ Node.js ที่เกี่ยวข้องกับการใช้การเรียกกลับคือการเรียกพวกเขามากกว่าหนึ่งครั้ง โดยทั่วไป ฟังก์ชันที่แพ็คเกจให้มาเพื่อทำบางสิ่งแบบอะซิงโครนัสได้รับการออกแบบให้คาดหวังฟังก์ชันเป็นอาร์กิวเมนต์สุดท้าย ซึ่งจะถูกเรียกเมื่องานอะซิงโครนัสเสร็จสิ้น:
module.exports.verifyPassword = function(user, password, done) { if(typeof password !== 'string') { done(new Error('password should be a string')) return } computeHash(password, user.passwordHashOpts, function(err, hash) { if(err) { done(err) return } done(null, hash === user.passwordHash) }) }
สังเกตว่ามีคำสั่ง return ทุกครั้งที่เรียก "เสร็จสิ้น" จนถึงครั้งสุดท้าย เนื่องจากการโทรกลับไม่ได้ยุติการดำเนินการของฟังก์ชันปัจจุบันโดยอัตโนมัติ หากมีการแสดงความคิดเห็น "การส่งคืน" ครั้งแรก การส่งรหัสผ่านที่ไม่ใช่สตริงไปยังฟังก์ชันนี้จะยังส่งผลให้มีการเรียก "computeHash" ขึ้นอยู่กับว่า “computeHash” จัดการกับสถานการณ์ดังกล่าวอย่างไร “เสร็จสิ้น” อาจถูกเรียกหลายครั้ง ใครก็ตามที่ใช้ฟังก์ชันนี้จากที่อื่นอาจถูกดักฟังโดยสมบูรณ์เมื่อมีการเรียกกลับที่พวกเขาส่งหลายครั้ง
ต้องใช้ความระมัดระวังเพื่อหลีกเลี่ยงข้อผิดพลาด Node.js นี้ นักพัฒนา Node.js บางรายมีนิสัยชอบเพิ่มคีย์เวิร์ด return ก่อนเรียกใช้ callback ทุกครั้ง:
if(err) { return done(err) }
ในฟังก์ชันแบบอะซิงโครนัสจำนวนมาก ค่าที่ส่งกลับแทบไม่มีนัยสำคัญ ดังนั้นวิธีนี้มักทำให้ง่ายต่อการหลีกเลี่ยงปัญหาดังกล่าว
ข้อผิดพลาด #3: การโทรกลับแบบซ้อนลึก
การเรียกกลับแบบซ้อนลึกซึ่งมักเรียกกันว่า "callback hell" ไม่ใช่ปัญหาของ Node.js ในตัวมันเอง อย่างไรก็ตาม สิ่งนี้อาจทำให้เกิดปัญหาในการทำให้โค้ดไม่สามารถควบคุมได้อย่างรวดเร็ว:
function handleLogin(..., done) { db.User.get(..., function(..., user) { if(!user) { return done(null, 'failed to log in') } utils.verifyPassword(..., function(..., okay) { if(okay) { return done(null, 'failed to log in') } session.login(..., function() { done(null, 'logged in') }) }) }) }
ยิ่งงานซับซ้อนมากเท่าไหร่ ก็ยิ่งแย่ลงเท่านั้น ด้วยการซ้อนการเรียกกลับในลักษณะนี้ เราจึงมักเกิดข้อผิดพลาดได้ง่าย อ่านยาก และดูแลรักษาโค้ดได้ยาก วิธีแก้ปัญหาหนึ่งคือการประกาศงานเหล่านี้เป็นฟังก์ชันเล็กๆ แล้วเชื่อมโยงเข้าด้วยกัน แม้ว่าหนึ่งในโซลูชันที่สะอาดที่สุด (น่าจะได้) สำหรับสิ่งนี้คือการใช้แพ็คเกจ Node.js ยูทิลิตี้ที่เกี่ยวข้องกับรูปแบบ JavaScript แบบอะซิงโครนัส เช่น Async.js:
function handleLogin(done) { async.waterfall([ function(done) { db.User.get(..., done) }, function(user, done) { if(!user) { return done(null, 'failed to log in') } utils.verifyPassword(..., function(..., okay) { done(null, user, okay) }) }, function(user, okay, done) { if(okay) { return done(null, 'failed to log in') } session.login(..., function() { done(null, 'logged in') }) } ], function() { // ... }) }
คล้ายกับ "async.waterfall" มีฟังก์ชันอื่นๆ จำนวนหนึ่งที่ Async.js มีไว้เพื่อจัดการกับรูปแบบอะซิงโครนัสที่แตกต่างกัน เพื่อความกระชับ เราใช้ตัวอย่างที่ง่ายกว่าที่นี่ แต่ความเป็นจริงมักจะแย่กว่านั้น
ข้อผิดพลาด #4: คาดว่าการโทรกลับจะทำงานพร้อมกัน
การเขียนโปรแกรมแบบอะซิงโครนัสพร้อมการเรียกกลับอาจไม่ใช่สิ่งที่ไม่เหมือนใครใน JavaScript และ Node.js แต่มีความรับผิดชอบต่อความนิยม สำหรับภาษาโปรแกรมอื่นๆ เราคุ้นเคยกับลำดับการดำเนินการที่คาดการณ์ได้ โดยที่คำสั่งสองคำสั่งจะดำเนินการทีละรายการ เว้นแต่จะมีคำสั่งเฉพาะเพื่อข้ามไปมาระหว่างคำสั่งต่างๆ ถึงอย่างนั้น สิ่งเหล่านี้มักจะจำกัดเฉพาะคำสั่งแบบมีเงื่อนไข คำสั่งแบบวนซ้ำ และการเรียกใช้ฟังก์ชัน
อย่างไรก็ตาม ใน JavaScript ด้วยการเรียกกลับ ฟังก์ชันบางอย่างอาจทำงานได้ไม่ดีจนกว่างานที่รออยู่จะเสร็จสิ้น การทำงานของฟังก์ชันปัจจุบันจะทำงานจนจบโดยไม่มีการหยุด:
function testTimeout() { console.log(“Begin”) setTimeout(function() { console.log(“Done!”) }, duration * 1000) console.log(“Waiting..”) }
คุณจะสังเกตเห็นว่าการเรียกใช้ฟังก์ชัน "testTimeout" จะเป็นการพิมพ์ "Begin" ก่อน จากนั้นจึงพิมพ์ "Waiting.." ตามด้วยข้อความ "Done!" หลังจากนั้นประมาณหนึ่งวินาที
อะไรก็ตามที่จำเป็นต้องเกิดขึ้นหลังจากการเรียกกลับต้องถูกเรียกใช้จากภายใน
ข้อผิดพลาด #5: กำหนดให้ "ส่งออก" แทนที่จะเป็น "module.exports"
Node.js ถือว่าแต่ละไฟล์เป็นโมดูลแยกขนาดเล็ก หากแพ็คเกจของคุณมีไฟล์สองไฟล์ บางทีอาจเป็น "a.js" และ "b.js" ดังนั้นสำหรับ "b.js" เพื่อเข้าถึงฟังก์ชันของ "a.js" "a.js" จะต้องส่งออกโดยเพิ่มคุณสมบัติลงใน วัตถุการส่งออก:

// a.js exports.verifyPassword = function(user, password, done) { ... }
เมื่อเสร็จแล้ว ใครก็ตามที่ต้องการ "a.js" จะได้รับอ็อบเจ็กต์ที่มีฟังก์ชันคุณสมบัติ "verifyPassword":
// b.js require('a.js') // { verifyPassword: function(user, password, done) { ... } }
อย่างไรก็ตาม ถ้าเราต้องการส่งออกฟังก์ชันนี้โดยตรง ไม่ใช่เป็นคุณสมบัติของวัตถุบางอย่างล่ะ เราสามารถเขียนทับการส่งออกเพื่อทำสิ่งนี้ แต่เราต้องไม่ถือว่าเป็นตัวแปรส่วนกลาง:
// a.js module.exports = function(user, password, done) { ... }
สังเกตว่าเรากำลังปฏิบัติต่อ "การส่งออก" เป็นคุณสมบัติของอ็อบเจ็กต์โมดูลอย่างไร ความแตกต่างระหว่าง "module.exports" และ "exports" มีความสำคัญมากและมักเป็นสาเหตุของความไม่พอใจในหมู่นักพัฒนา Node.js รายใหม่
ข้อผิดพลาด #6: โยนข้อผิดพลาดจากการโทรกลับภายใน
JavaScript มีแนวคิดเรื่องข้อยกเว้น การเลียนแบบไวยากรณ์ของภาษาดั้งเดิมเกือบทั้งหมดด้วยการสนับสนุนการจัดการข้อยกเว้น เช่น Java และ C++ ทำให้ JavaScript สามารถ "โยน" และตรวจจับข้อยกเว้นในบล็อก try-catch:
function slugifyUsername(username) { if(typeof username === 'string') { throw new TypeError('expected a string username, got '+(typeof username)) } // ... } try { var usernameSlug = slugifyUsername(username) } catch(e) { console.log('Oh no!') }
อย่างไรก็ตาม try-catch จะไม่ทำงานอย่างที่คุณคาดหวังในสถานการณ์แบบอะซิงโครนัส ตัวอย่างเช่น หากคุณต้องการปกป้องโค้ดจำนวนมากที่มีกิจกรรมแบบอะซิงโครนัสจำนวนมากด้วยบล็อก try-catch ขนาดใหญ่บล็อกเดียว โค้ดดังกล่าวอาจไม่ได้ผลเสมอไป:
try { db.User.get(userId, function(err, user) { if(err) { throw err } // ... usernameSlug = slugifyUsername(user.username) // ... }) } catch(e) { console.log('Oh no!') }
หากการเรียกกลับ "db.User.get" ทำงานแบบอะซิงโครนัส ขอบเขตที่มีบล็อก try-catch จะหายไปจากบริบทเป็นเวลานานเพื่อให้ยังคงสามารถตรวจจับข้อผิดพลาดที่เกิดจากภายในการโทรกลับได้
นี่คือวิธีจัดการกับข้อผิดพลาดในวิธีที่ต่างออกไปใน Node.js และนั่นทำให้จำเป็นต้องปฏิบัติตามรูปแบบ (err, …) บนอาร์กิวเมนต์ของฟังก์ชันเรียกกลับทั้งหมด - อาร์กิวเมนต์แรกของการเรียกกลับทั้งหมดคาดว่าจะเกิดข้อผิดพลาดหากมีเกิดขึ้น .
ข้อผิดพลาด #7: สมมติว่าตัวเลขเป็นประเภทข้อมูลจำนวนเต็ม
ตัวเลขใน JavaScript เป็นจุดลอยตัว - ไม่มีประเภทข้อมูลจำนวนเต็ม คุณคงไม่คิดว่านี่จะเป็นปัญหา เพราะไม่ค่อยพบตัวเลขที่มีขนาดใหญ่พอที่จะเน้นย้ำถึงขีดจำกัดของการลอยตัว นั่นคือเมื่อข้อผิดพลาดที่เกี่ยวข้องกับสิ่งนี้เกิดขึ้น เนื่องจากตัวเลขทศนิยมสามารถเก็บการแสดงจำนวนเต็มได้เฉพาะค่าหนึ่ง การเกินค่านั้นในการคำนวณใดๆ จะทำให้ค่าดังกล่าวยุ่งเหยิงทันที ดูเหมือนว่าแปลก สิ่งต่อไปนี้จะประเมินเป็นจริงใน Node.js:
Math.pow(2, 53)+1 === Math.pow(2, 53)
น่าเสียดาย นิสัยแปลก ๆ ของตัวเลขใน JavaScript ไม่ได้สิ้นสุดที่นี่ แม้ว่า Numbers จะเป็นทศนิยม แต่ตัวดำเนินการที่ทำงานบนชนิดข้อมูลจำนวนเต็มก็ทำงานที่นี่เช่นกัน:
5 % 2 === 1 // true 5 >> 1 === 2 // true
อย่างไรก็ตาม ต่างจากตัวดำเนินการเลขคณิต ตัวดำเนินการระดับบิตและตัวดำเนินการ shift ทำงานเฉพาะกับตัวเลข "จำนวนเต็ม" ขนาดใหญ่ที่ต่อท้าย 32 บิตเท่านั้น ตัวอย่างเช่น การพยายามเปลี่ยน “Math.pow(2, 53)” ด้วย 1 จะประเมินเป็น 0 เสมอ การพยายามเปลี่ยนระดับบิตหรือเท่ากับ 1 ด้วยจำนวนที่มากเท่ากันนั้นจะประเมินเป็น 1
Math.pow(2, 53) / 2 === Math.pow(2, 52) // true Math.pow(2, 53) >> 1 === 0 // true Math.pow(2, 53) | 1 === 1 // true
คุณอาจแทบไม่ต้องจัดการกับตัวเลขจำนวนมาก แต่ถ้าเป็นเช่นนั้น มีไลบรารีจำนวนเต็มขนาดใหญ่จำนวนมากที่ใช้การดำเนินการทางคณิตศาสตร์ที่สำคัญกับตัวเลขที่มีความแม่นยำสูง เช่น node-bigint
ข้อผิดพลาด #8: ละเลยข้อดีของการสตรีม API
สมมติว่าเราต้องการสร้างเว็บเซิร์ฟเวอร์ที่เหมือนพร็อกซี่ขนาดเล็กที่ตอบสนองต่อคำขอโดยดึงเนื้อหาจากเว็บเซิร์ฟเวอร์อื่น ตัวอย่างเช่น เราจะสร้างเว็บเซิร์ฟเวอร์ขนาดเล็กที่ให้บริการอิมเมจ Gravatar:
var http = require('http') var crypto = require('crypto') http.createServer() .on('request', function(req, res) { var email = req.url.substr(req.url.lastIndexOf('/')+1) if(!email) { res.writeHead(404) return res.end() } var buf = new Buffer(1024*1024) http.get('http://www.gravatar.com/avatar/'+crypto.createHash('md5').update(email).digest('hex'), function(resp) { var size = 0 resp.on('data', function(chunk) { chunk.copy(buf, size) size += chunk.length }) .on('end', function() { res.write(buf.slice(0, size)) res.end() }) }) }) .listen(8080)
ในตัวอย่างเฉพาะของปัญหา Node.js เรากำลังดึงรูปภาพจาก Gravatar อ่านเป็นบัฟเฟอร์ จากนั้นจึงตอบสนองต่อคำขอ นี่ไม่ใช่สิ่งที่เลวร้ายนัก เนื่องจากรูปภาพ Gravatar มีขนาดไม่ใหญ่เกินไป อย่างไรก็ตาม ลองนึกภาพว่าขนาดของเนื้อหาที่เราพร็อกซี่นั้นมีขนาดหลายพันเมกะไบต์หรือไม่ แนวทางที่ดีกว่ามากคือ:
http.createServer() .on('request', function(req, res) { var email = req.url.substr(req.url.lastIndexOf('/')+1) if(!email) { res.writeHead(404) return res.end() } http.get('http://www.gravatar.com/avatar/'+crypto.createHash('md5').update(email).digest('hex'), function(resp) { resp.pipe(res) }) }) .listen(8080)
ที่นี่ เราดึงภาพและเพียงส่งการตอบสนองไปยังไคลเอนต์ เราไม่จำเป็นต้องอ่านเนื้อหาทั้งหมดลงในบัฟเฟอร์ก่อนให้บริการ
ข้อผิดพลาด #9: การใช้ Console.log เพื่อจุดประสงค์ในการดีบัก
ใน Node.js "console.log" ช่วยให้คุณสามารถพิมพ์เกือบทุกอย่างไปยังคอนโซลได้ ส่งอ็อบเจ็กต์ไปที่อ็อบเจ็กต์และจะพิมพ์เป็นอ็อบเจกต์ JavaScript ยอมรับจำนวนอาร์กิวเมนต์ตามอำเภอใจและพิมพ์ทั้งหมดโดยแบ่งพื้นที่อย่างเป็นระเบียบ มีสาเหตุหลายประการที่นักพัฒนาอาจรู้สึกอยากที่จะใช้สิ่งนี้เพื่อดีบั๊กโค้ดของเขา อย่างไรก็ตาม ขอแนะนำอย่างยิ่งให้คุณหลีกเลี่ยง “console.log” ในโค้ดจริง คุณควรหลีกเลี่ยงการเขียน “console.log” ให้ทั่วทั้งโค้ดเพื่อแก้ไขข้อบกพร่อง จากนั้นแสดงความคิดเห็นเมื่อไม่ต้องการใช้อีกต่อไป ให้ใช้ไลบรารีอันน่าทึ่งที่สร้างขึ้นมาเพื่อสิ่งนี้แทน เช่น การดีบัก
แพ็คเกจเหล่านี้มีวิธีที่สะดวกในการเปิดและปิดการดีบักบางบรรทัดเมื่อคุณเริ่มแอปพลิเคชัน ตัวอย่างเช่น ด้วยการดีบัก เป็นไปได้ที่จะป้องกันไม่ให้บรรทัดการดีบักถูกพิมพ์ไปยังเทอร์มินัลโดยไม่ได้ตั้งค่าตัวแปรสภาพแวดล้อม DEBUG ใช้ง่าย:
// app.js var debug = require('debug')('app') debug('Hello, %s!', 'world')
หากต้องการเปิดใช้งานบรรทัดดีบัก ให้รันโค้ดนี้โดยตั้งค่าตัวแปรสภาพแวดล้อม DEBUG เป็น "app" หรือ "*":
DEBUG=app node app.js
ข้อผิดพลาด #10: ไม่ใช้โปรแกรมหัวหน้างาน
ไม่ว่าโค้ด Node.js ของคุณกำลังทำงานอยู่ในเวอร์ชันที่ใช้งานจริงหรือในสภาพแวดล้อมการพัฒนาในพื้นที่ของคุณ โปรแกรมผู้ควบคุมดูแลที่สามารถจัดการโปรแกรมของคุณก็เป็นสิ่งที่มีประโยชน์อย่างยิ่ง แนวทางปฏิบัติอย่างหนึ่งที่นักพัฒนาออกแบบและปรับใช้แอปพลิเคชันสมัยใหม่มักแนะนำ แนะนำให้โค้ดของคุณควรล้มเหลวอย่างรวดเร็ว หากเกิดข้อผิดพลาดที่ไม่คาดคิด อย่าพยายามจัดการกับมัน ให้โปรแกรมของคุณหยุดทำงานและให้หัวหน้างานเริ่มการทำงานใหม่ภายในไม่กี่วินาที ประโยชน์ของโปรแกรมผู้ควบคุมไม่ได้จำกัดอยู่เพียงการรีสตาร์ทโปรแกรมที่ขัดข้องเท่านั้น เครื่องมือเหล่านี้ช่วยให้คุณสามารถรีสตาร์ทโปรแกรมเมื่อเกิดความผิดพลาด รวมทั้งเริ่มการทำงานใหม่เมื่อมีการเปลี่ยนแปลงไฟล์บางไฟล์ สิ่งนี้ทำให้การพัฒนาโปรแกรม Node.js เป็นประสบการณ์ที่น่าพึงพอใจยิ่งขึ้น
มีโปรแกรมหัวหน้างานมากมายสำหรับ Node.js ตัวอย่างเช่น:
pm2
ตลอดไป
โนเดมอน
หัวหน้างาน
เครื่องมือเหล่านี้มาพร้อมกับข้อดีและข้อเสีย บางตัวดีสำหรับการจัดการหลายแอพพลิเคชั่นในเครื่องเดียวกัน ในขณะที่บางตัวจัดการบันทึกได้ดีกว่า อย่างไรก็ตาม หากคุณต้องการเริ่มต้นกับโปรแกรมดังกล่าว ทั้งหมดนี้เป็นตัวเลือกที่ยุติธรรม
บทสรุป
อย่างที่คุณทราบ ปัญหาบางอย่างของ Node.js เหล่านี้อาจส่งผลกระทบร้ายแรงต่อโปรแกรมของคุณ บางอย่างอาจเป็นสาเหตุของความหงุดหงิดในขณะที่คุณพยายามใช้สิ่งที่ง่ายที่สุดใน Node.js แม้ว่า Node.js จะทำให้ผู้มาใหม่เริ่มต้นได้ง่ายมาก แต่ก็ยังมีพื้นที่ที่ง่ายต่อการสับสน นักพัฒนาซอฟต์แวร์จากภาษาการเขียนโปรแกรมอื่นๆ อาจสามารถเกี่ยวข้องกับปัญหาเหล่านี้ได้ แต่ข้อผิดพลาดเหล่านี้พบได้บ่อยในหมู่นักพัฒนา Node.js ใหม่ โชคดีที่หลีกเลี่ยงได้ง่าย ฉันหวังว่าคู่มือสั้น ๆ นี้จะช่วยให้ผู้เริ่มต้นเขียนโค้ดได้ดีขึ้นใน Node.js และพัฒนาซอฟต์แวร์ที่เสถียรและมีประสิทธิภาพสำหรับพวกเราทุกคน