इस विषय पर कई अलग-अलग स्रोतों से एक सारांश और उद्धरण दिया गया है जिसमें चयनित ब्लॉग पोस्ट के कोड उदाहरण और उद्धरण शामिल हैं। सर्वोत्तम प्रथाओं की पूरी सूची यहां पाई जा सकती है
Node.JS त्रुटि से निपटने के सर्वोत्तम अभ्यास
नंबर 1: Async त्रुटि हैंडलिंग के लिए वादों का उपयोग करें
टीएल; डीआर: कॉलबैक शैली में async त्रुटियों को संभालना शायद नरक का सबसे तेज़ तरीका है (उर्फ कयामत का पिरामिड)। सबसे अच्छा उपहार जो आप अपने कोड को दे सकते हैं वह एक सम्मानित वादा पुस्तकालय के बजाय उपयोग कर रहा है जो बहुत कॉम्पैक्ट और परिचित कोड सिंटैक्स प्रदान करता है जैसे कि कोशिश
अन्यथा: Node.JS कॉलबैक शैली, फ़ंक्शन (इरेटा, प्रतिक्रिया), अनौपचारिक कोड के लिए एक आशाजनक तरीका है, जो आकस्मिक कोड, अत्यधिक नेस्टिंग और अजीब कोडिंग पैटर्न के साथ त्रुटि से निपटने के मिश्रण के कारण होता है।
कोड उदाहरण - अच्छा
doWork()
.then(doWork)
.then(doError)
.then(doWork)
.catch(errorHandler)
.then(verify);
कोड उदाहरण विरोधी पैटर्न - कॉलबैक शैली त्रुटि हैंडलिंग
getData(someParameter, function(err, result){
if(err != null)
//do something like calling the given callback function and pass the error
getMoreData(a, function(err, result){
if(err != null)
//do something like calling the given callback function and pass the error
getMoreData(b, function(c){
getMoreData(d, function(e){
...
});
});
});
});
});
ब्लॉग उद्धरण: "हम वादों के साथ एक समस्या है"
(ब्लॉग पाउच से, कीवर्ड "नोड प्रॉमिस" के लिए 11 वें स्थान पर)
"... और वास्तव में, कॉलबैक कुछ और भी भयावह करते हैं: वे हमें ढेर से वंचित करते हैं, जो कि हम आमतौर पर प्रोग्रामिंग भाषाओं में दी जाने वाली चीज है। एक स्टैक के बिना कोड लिखना एक ब्रेक पैडल के बिना कार चलाना बहुत पसंद है: आप एहसास नहीं है कि आपको कितनी बुरी तरह से इसकी आवश्यकता है, जब तक आप इसके लिए नहीं पहुंचते हैं और यह वहां नहीं है। वादों का पूरा बिंदु हमें उस भाषा के मूल सिद्धांतों को वापस देना है जो हम खो गए थे जब हम async गए थे: वापसी, फेंक और स्टैक। लेकिन। उन्हें लाभ लेने के लिए सही तरीके से वादों का उपयोग करने का तरीका जानना होगा। ”
नंबर 2: केवल अंतर्निहित त्रुटि ऑब्जेक्ट का उपयोग करें
TL; DR: कोड को देखने में काफी सामान्य है जो त्रुटियों को स्ट्रिंग के रूप में या एक कस्टम प्रकार के रूप में फेंकता है - यह त्रुटि हैंडलिंग तर्क और मॉड्यूल के बीच अंतर को जटिल करता है। चाहे आप किसी वादे को अस्वीकार करते हैं, अपवाद को फेंक देते हैं या त्रुटि फेंकते हैं - Node.JS अंतर्निहित त्रुटि ऑब्जेक्ट का उपयोग करने से एकरूपता बढ़ जाती है और त्रुटि जानकारी के नुकसान को रोकता है
अन्यथा: जब कुछ मॉड्यूल निष्पादित करते हैं, तो अनिश्चित होने के बदले में किस प्रकार की त्रुटियां आती हैं - इससे आने वाले अपवाद के बारे में तर्क करना और उसे संभालना बहुत कठिन हो जाता है। यहां तक कि, त्रुटियों का वर्णन करने के लिए कस्टम प्रकारों का उपयोग करने से स्टैक ट्रेस जैसी महत्वपूर्ण त्रुटि जानकारी का नुकसान हो सकता है!
कोड उदाहरण - इसे सही करना
//throwing an Error from typical function, whether sync or async
if(!productToAdd)
throw new Error("How can I add new product when no value provided?");
//'throwing' an Error from EventEmitter
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
//'throwing' an Error from a Promise
return new promise(function (resolve, reject) {
DAL.getProduct(productToAdd.id).then((existingProduct) =>{
if(existingProduct != null)
return reject(new Error("Why fooling us and trying to add an existing product?"));
कोड उदाहरण विरोधी पैटर्न
//throwing a String lacks any stack trace information and other important properties
if(!productToAdd)
throw ("How can I add new product when no value provided?");
ब्लॉग उद्धरण: "एक स्ट्रिंग एक त्रुटि नहीं है"
(ब्लॉग से निकाले गए, कीवर्ड के लिए 6 रैंक "Node.JS त्रुटि")
"... एक त्रुटि के बजाय एक स्ट्रिंग से गुजरने से मॉड्यूल के बीच अंतर कम हो जाता है। यह एपीआई के साथ अनुबंधों को तोड़ता है जो कि उदाहरण के लिए त्रुटि जांच कर सकता है, या जो त्रुटि के बारे में अधिक जानना चाहते हैं । त्रुटि वस्तुओं, जैसा कि हम देखेंगे, बहुत हैं। आधुनिक जावास्क्रिप्ट इंजन में दिलचस्प गुण कंस्ट्रक्टर को भेजे गए संदेश को रखने के अलावा .. "
संख्या 3: प्रोग्रामर त्रुटियों के लिए प्रचालनात्मक भेद
TL; DR: ऑपरेशंस एरर (जैसे एपीआई को एक अमान्य इनपुट मिला) उन मामलों को संदर्भित करता है जहां त्रुटि प्रभाव को पूरी तरह से समझा जाता है और इसे सोच-समझकर हैंडल किया जा सकता है। दूसरी ओर, प्रोग्रामर त्रुटि (जैसे अपरिभाषित चर को पढ़ने की कोशिश करना) अज्ञात कोड विफलताओं को संदर्भित करता है जो आवेदन को फिर से शुरू करने के लिए सुशोभित करने के लिए निर्देशित करते हैं
अन्यथा: त्रुटि सामने आने पर आप हमेशा एप्लिकेशन को पुनरारंभ कर सकते हैं, लेकिन ~ 5000 ऑनलाइन उपयोगकर्ताओं को एक छोटी और अनुमानित त्रुटि (परिचालन त्रुटि) के कारण नीचे क्यों दे सकते हैं? विपरीत भी आदर्श नहीं है - अज्ञात समस्या (प्रोग्रामर त्रुटि) होने पर आवेदन को रखने से अनपेक्षित व्यवहार हो सकता है। दोनों को विभेदित करना कार्य को सावधानीपूर्वक करने और दिए गए संदर्भ के आधार पर एक संतुलित दृष्टिकोण लागू करने की अनुमति देता है
कोड उदाहरण - इसे सही करना
//throwing an Error from typical function, whether sync or async
if(!productToAdd)
throw new Error("How can I add new product when no value provided?");
//'throwing' an Error from EventEmitter
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
//'throwing' an Error from a Promise
return new promise(function (resolve, reject) {
DAL.getProduct(productToAdd.id).then((existingProduct) =>{
if(existingProduct != null)
return reject(new Error("Why fooling us and trying to add an existing product?"));
कोड उदाहरण - परिचालन (विश्वसनीय) के रूप में एक त्रुटि चिह्नित करना
//marking an error object as operational
var myError = new Error("How can I add new product when no value provided?");
myError.isOperational = true;
//or if you're using some centralized error factory (see other examples at the bullet "Use only the built-in Error object")
function appError(commonType, description, isOperational) {
Error.call(this);
Error.captureStackTrace(this);
this.commonType = commonType;
this.description = description;
this.isOperational = isOperational;
};
throw new appError(errorManagement.commonErrors.InvalidInput, "Describe here what happened", true);
//error handling code within middleware
process.on('uncaughtException', function(error) {
if(!error.isOperational)
process.exit(1);
});
ब्लॉग उद्धरण : "अन्यथा आप राज्य को जोखिम में डालते हैं" (ब्लॉग डीबग करने योग्य से, कीवर्ड "Node.JS अनकैप्ड" के लिए 3 रैंक पर))
" ... जावास्क्रिप्ट में कैसे फेंक काम करता है की बहुत ही प्रकृति से, लगभग कभी भी सुरक्षित रूप से" पिक अप नहीं है जहाँ आप छोड़ दिया है ", संदर्भ लीक के बिना, या अपरिभाषित भंगुर राज्य के कुछ अन्य प्रकार बनाने का सबसे सुरक्षित तरीका है। प्रतिक्रिया देने का सबसे सुरक्षित तरीका। एक फेंकने की त्रुटि प्रक्रिया को बंद करने के लिए है । बेशक, एक सामान्य वेब सर्वर में, आपके पास कई कनेक्शन खुले हो सकते हैं, और यह अचानक बंद करने के लिए उचित नहीं है क्योंकि किसी अन्य व्यक्ति द्वारा एक त्रुटि को ट्रिगर किया गया था। बेहतर दृष्टिकोण है। उस अनुरोध के लिए एक त्रुटि प्रतिक्रिया भेजें जो त्रुटि को ट्रिगर करता है, जबकि दूसरों को उनके सामान्य समय में खत्म करने देता है, और उस कार्यकर्ता में नए अनुरोधों को सुनना बंद कर देता है "
संख्या 4: मध्य के भीतर नहीं बल्कि इसके माध्यम से, केंद्रीय रूप से त्रुटियों को संभालें
टीएल; डीआर: त्रुटि से निपटने के तर्क जैसे कि मेल टू एडमिन और लॉगिंग को एक समर्पित और केंद्रीकृत ऑब्जेक्ट में इनकैप्सुलेट किया जाना चाहिए कि सभी एंड-पॉइंट्स (जैसे एक्सप्रेस मिडलवेयर, क्रॉन जॉब्स, यूनिट-टेस्टिंग) कॉल तब आती है जब कोई त्रुटि आती है।
अन्यथा: एक ही स्थान पर त्रुटियों को नहीं संभालने से कोड दोहराव हो सकता है और शायद ऐसी त्रुटियां जो अनुचित तरीके से नियंत्रित की जाती हैं
कोड उदाहरण - एक सामान्य त्रुटि प्रवाह
//DAL layer, we don't handle errors here
DB.addDocument(newCustomer, (error, result) => {
if (error)
throw new Error("Great error explanation comes here", other useful parameters)
});
//API route code, we catch both sync and async errors and forward to the middleware
try {
customerService.addNew(req.body).then(function (result) {
res.status(200).json(result);
}).catch((error) => {
next(error)
});
}
catch (error) {
next(error);
}
//Error handling middleware, we delegate the handling to the centrzlied error handler
app.use(function (err, req, res, next) {
errorHandler.handleError(err).then((isOperationalError) => {
if (!isOperationalError)
next(err);
});
});
ब्लॉग उद्धरण: "कभी-कभी निचले स्तर उनके कॉलर को त्रुटि का प्रचार करने के अलावा कुछ भी उपयोगी नहीं कर सकते हैं" (ब्लॉग जॉयेंट से, कीवर्ड के लिए 1 रैंक "Node.JS त्रुटि हैंडलिंग")
"... आप स्टैक के कई स्तरों पर एक ही त्रुटि को समाप्त कर सकते हैं। यह तब होता है जब निचले स्तर अपने कॉलर को त्रुटि को प्रचारित करने के अलावा कुछ भी उपयोगी नहीं कर सकते हैं, जो त्रुटि को इसके कॉलर को प्रसारित करता है, और इसी तरह। अक्सर। केवल शीर्ष-स्तरीय कॉलर को पता है कि उपयुक्त प्रतिक्रिया क्या है, चाहे वह ऑपरेशन को फिर से करना हो, उपयोगकर्ता को त्रुटि की रिपोर्ट करें, या कुछ और। लेकिन इसका मतलब यह नहीं है कि आपको सभी त्रुटियों को एक ही शीर्ष-स्तर पर रिपोर्ट करने का प्रयास करना चाहिए। कॉलबैक, क्योंकि वह कॉलबैक स्वयं नहीं जान सकता कि त्रुटि किस संदर्भ में हुई थी "
नंबर 5: स्वैगर का उपयोग करते हुए दस्तावेज़ एपीआई त्रुटियाँ
टीएल; डीआर: अपने एपीआई कॉलर्स को बताएं कि कौन सी त्रुटियां बदले में आ सकती हैं ताकि वे दुर्घटनाग्रस्त हुए बिना सोचे समझे इन्हें संभाल सकें। यह आमतौर पर स्वैगर की तरह REST API डॉक्यूमेंट फ्रेमवर्क के साथ किया जाता है
अन्यथा: एक API क्लाइंट केवल क्रैश करने और पुनः आरंभ करने का निर्णय ले सकता है क्योंकि उसे एक त्रुटि मिली जिसे वह समझ नहीं पाया। ध्यान दें: आपके API का कॉलर आप पर हो सकता है (बहुत ही सूक्ष्म वातावरण में विशिष्ट)
ब्लॉग उद्धरण: "आपको अपने कॉलर्स को बताना होगा कि क्या त्रुटियां हो सकती हैं" (ब्लॉग जॉयेंट से, "Node.JS लॉगिंग" कीवर्ड के लिए 1 रैंक)
… हमने त्रुटियों को संभालने के तरीके के बारे में बात की है, लेकिन जब आप एक नया फ़ंक्शन लिख रहे हैं, तो आप अपने कोड को त्रुटियों को कैसे वितरित करेंगे? ... यदि आप नहीं जानते कि क्या त्रुटियां हो सकती हैं या वे नहीं जानते कि उनका क्या मतलब है, तो दुर्घटना के अलावा आपका कार्यक्रम सही नहीं हो सकता है। इसलिए यदि आप एक नया फ़ंक्शन लिख रहे हैं, तो आपको अपने कॉलर्स को बताना होगा कि क्या गलतियाँ हो सकती हैं और वे क्या कर रहे हैं
नंबर 6: किसी अजनबी के शहर में आने पर प्रक्रिया को शान्तिपूर्वक बंद करें
TL; DR: जब कोई अज्ञात त्रुटि होती है (एक डेवलपर त्रुटि, सबसे अच्छा अभ्यास नंबर # 3 देखें) - अनुप्रयोग स्वास्थ्यता के बारे में अनिश्चितता है। एक सामान्य अभ्यास फॉरएवर और पीएम 2 जैसे 'स्टार्टर' टूल का उपयोग करके सावधानीपूर्वक प्रक्रिया को फिर से शुरू करने का सुझाव देता है
अन्यथा: जब कोई अपरिचित अपवाद पकड़ा जाता है, तो कुछ वस्तु दोषपूर्ण स्थिति में हो सकती है (उदाहरण के लिए एक घटना उत्सर्जक जो विश्व स्तर पर उपयोग की जाती है और कुछ आंतरिक विफलता के कारण घटनाओं को नहीं रोकती) और भविष्य के सभी अनुरोध विफल हो सकते हैं या पागलपन का व्यवहार कर सकते हैं
कोड उदाहरण - यह तय करना कि दुर्घटनाग्रस्त होना है या नहीं
//deciding whether to crash when an uncaught exception arrives
//Assuming developers mark known operational errors with error.isOperational=true, read best practice #3
process.on('uncaughtException', function(error) {
errorManagement.handler.handleError(error);
if(!errorManagement.handler.isTrustedError(error))
process.exit(1)
});
//centralized error handler encapsulates error-handling related logic
function errorHandler(){
this.handleError = function (error) {
return logger.logError(err).then(sendMailToAdminIfCritical).then(saveInOpsQueueIfCritical).then(determineIfOperationalError);
}
this.isTrustedError = function(error)
{
return error.isOperational;
}
ब्लॉग उद्धरण: "त्रुटि से निपटने पर विचारों के तीन स्कूल हैं" (ब्लॉग jsrecipes से)
... मुख्य रूप से त्रुटि से निपटने पर विचारों के तीन स्कूल हैं: 1. एप्लिकेशन को क्रैश होने दें और इसे पुनः आरंभ करें। 2. सभी संभावित त्रुटियों से निपटने और दुर्घटना कभी नहीं। 3. दोनों के बीच संतुलित दृष्टिकोण
नंबर 7: त्रुटियों की दृश्यता बढ़ाने के लिए एक परिपक्व लकड़हारे का उपयोग करें
टीएल; डीआर: विंस्टन, ब्यून या लॉग 4 जे जैसे परिपक्व लॉगिंग टूल का एक सेट, त्रुटि खोज और समझ को गति देगा। तो कंसोल के बारे में भूल जाओ।
अन्यथा: कंसोल के माध्यम से स्कोलिंग्स। स्लोगन या मैन्युअल रूप से मैसेजिंग टेक्स्ट फाइल के माध्यम से बिना क्वेरी टूल या एक सभ्य लॉग व्यूअर के साथ काम के दौरान आपको व्यस्त रख सकते हैं
कोड उदाहरण - कार्रवाई में विंस्टन लकड़हारा
//your centralized logger object
var logger = new winston.Logger({
level: 'info',
transports: [
new (winston.transports.Console)(),
new (winston.transports.File)({ filename: 'somefile.log' })
]
});
//custom code somewhere using the logger
logger.log('info', 'Test Log Message with some parameter %s', 'some parameter', { anything: 'This is metadata' });
ब्लॉग उद्धरण: "कुछ आवश्यकताओं की पहचान करें (एक लकड़हारे के लिए):" (ब्लॉग स्ट्रॉन्ग्लॉग से)
… कुछ आवश्यकताओं को पहचानें (एक लकड़हारे के लिए): 1. समय प्रत्येक लॉग लाइन पर मुहर लगाता है। यह एक बहुत आत्म व्याख्यात्मक है - आपको यह बताने में सक्षम होना चाहिए कि प्रत्येक लॉग प्रविष्टि कब हुई। 2. लॉगिंग प्रारूप को मनुष्यों के साथ-साथ मशीनों द्वारा आसानी से पचने योग्य होना चाहिए। 3. कई विन्यास गंतव्य धाराओं के लिए अनुमति देता है। उदाहरण के लिए, आप एक फ़ाइल में ट्रेस लॉग लिख रहे होंगे, लेकिन जब कोई त्रुटि सामने आती है, तो उसी फ़ाइल पर लिखें, फिर त्रुटि फ़ाइल में और उसी समय एक ईमेल भेजें ...
नंबर 8: एपीएम उत्पादों का उपयोग करके त्रुटियों और डाउनटाइम की खोज करें
TL; DR: मॉनिटरिंग और परफॉर्मेंस प्रोडक्ट्स (उर्फ APM) आपके कोडबेस या एपीआई को तुरंत गेज करते हैं ताकि वे ऑटो-जादुई रूप से त्रुटियों, क्रैश और धीमी भागों को उजागर कर सकें जो आप गायब थे।
अन्यथा: आप एपीआई प्रदर्शन और डाउनटाइम्स को मापने के लिए बहुत प्रयास कर सकते हैं, शायद आपको कभी पता नहीं चलेगा कि वास्तविक दुनिया के परिदृश्य में आपके सबसे धीमे कोड भाग कौन से हैं और ये यूएक्स को कैसे प्रभावित करते हैं
ब्लॉग उद्धरण: "एपीएम उत्पाद खंड" (ब्लॉग योनी गोल्डबर्ग से)
"... एपीएम उत्पादों में 3 प्रमुख खंड होते हैं: 1. वेबसाइट या एपीआई निगरानी - बाहरी सेवाएं जो लगातार HTTP अनुरोधों के माध्यम से अपटाइम और प्रदर्शन की निगरानी करती हैं। कुछ ही मिनटों में सेटअप किया जा सकता है। निम्नलिखित कुछ चयनित दावेदार हैं: पीएसडीआई, अपटाइम रोबोट और न्यू रिले
2। । कोड इंस्ट्रूमेंटेशन - उत्पाद परिवार, जो अनुप्रयोग के भीतर एक एजेंट को सुविधा कोड पहचान, अपवाद आँकड़े, प्रदर्शन और कई और अधिक लाभ के लिए एम्बेड करने की आवश्यकता है। कुछ चयनित दावेदार हैं: नया रेलिक, ऐप डायनेमिक्स
3. ऑपरेशनल इंटेलिजेंस डैशबोर्ड -उत्पादों की ये पंक्ति मेट्रिक्स और क्यूरेटेड सामग्री के साथ ऑप्स टीम की सुविधा पर केंद्रित है जो आसानी से आवेदन प्रदर्शन में शीर्ष पर रहने में मदद करता है। इसमें आमतौर पर सूचना के कई स्रोतों (एप्लिकेशन लॉग, डीबी लॉग, सर्वर लॉग, आदि) और अपफ्रंट डैशबोर्ड डिज़ाइन कार्य शामिल होते हैं। कुछ चुनिंदा दावेदार निम्नलिखित हैं: दातडोग, स्प्लंक "
ऊपर एक छोटा संस्करण है - यहां और अधिक सर्वोत्तम अभ्यास और उदाहरण देखें