
पोस्ट में लेख
"Node.js में त्रुटि हैंडलिंग" का अनुवाद शामिल है, जिसे
जॉयंट कर्मचारियों द्वारा तैयार किया गया था। यह लेख 28 मार्च 2014 को कंपनी की वेबसाइट पर प्रकाशित किया गया था। डेव पाचेको
बताते हैं कि लेख का उद्देश्य डेवलपर्स के बीच अशांति को खत्म करना है, जो नोड्स.जेएस में बग के साथ काम करने के लिए सर्वोत्तम प्रथाओं के बारे में है, साथ ही साथ नौसिखिया डेवलपर्स के लिए अक्सर उठने वाले सवालों का जवाब देना है।
Node.js में त्रुटि हैंडलिंग
जैसा कि आप Node.js में महारत हासिल करते हैं, आप सही त्रुटि से ध्यान हटाने के बिना पर्याप्त रूप से लंबे समय तक प्रोग्राम लिख सकते हैं। हालांकि, Node.js पर गंभीर परियोजनाओं को विकसित करने के लिए इस समस्या के प्रति सचेत दृष्टिकोण की आवश्यकता है।
शुरुआती डेवलपर्स में अक्सर निम्नलिखित प्रश्न होते हैं:
- क्या किसी फ़ंक्शन से त्रुटि वापस करने के लिए
throw
का उपयोग करना संभव है, या क्या मुझे तर्क के रूप में त्रुटि ऑब्जेक्ट पास करके कॉलबैक फ़ंक्शन को कॉल करना चाहिए? EventEmitter वर्ग की एक वस्तु के लिए घटना 'error'
उत्पन्न करने के लिए किन मामलों में आवश्यक है? - क्या मुझे फ़ंक्शन को दिए गए तर्कों की जाँच करने की आवश्यकता है? क्या होगा अगर गलत तर्क समारोह में पारित हो जाते हैं? क्या इस मामले में एक अपवाद को फेंकना या कॉलबैक फ़ंक्शन को कॉल करना आवश्यक है, इसके लिए एक त्रुटि पारित करना?
- क्या प्रोग्राम के आधार पर त्रुटियों को प्रोग्रामिक रूप से अलग करना संभव है ताकि एप्लिकेशन उनके प्रकार (उदाहरण के लिए, "खराब अनुरोध" या "सेवा अनुपलब्ध") के अनुसार त्रुटियों को ठीक से संभाल सके?
- कोई फ़ंक्शन किसी त्रुटि की घटना के बारे में सबसे अधिक जानकारीपूर्ण तरीके से "सूचित" कैसे कर सकता है ताकि वह इसे सही ढंग से संभाल सके?
- क्या मुझे कार्यक्रम में "बग" के कारण होने वाली त्रुटियों को संभालने की आवश्यकता है?
इस लेख में सात भाग हैं:
- परिचय। तथ्य यह है कि पाठक को लेख पढ़ने से पहले पता होना चाहिए।
- प्रोग्राम एरर और प्रोग्रामर एरर्स। त्रुटियों के प्रकार के साथ परिचित।
- समारोह लेखन टेम्पलेट्स। लेखन कार्यों के मौलिक सिद्धांत जो त्रुटियों के साथ सही काम को लागू करते हैं।
- लेखन कार्यों के लिए नियम। कार्य करते समय दिशानिर्देशों की एक सूची जिसका पालन किया जाना चाहिए।
- एक उदाहरण है। एक फ़ंक्शन लिखने का एक उदाहरण।
- सारांश। लेख में विचार किए गए मुख्य बिंदुओं की संक्षिप्त प्रस्तुति।
- आवेदन। त्रुटि ऑब्जेक्ट के लिए सामान्य फ़ील्ड नाम।
1. परिचय
पाठक को माना जाता है:
- जावास्क्रिप्ट, जावा, पायथन, सी ++, या किसी अन्य समान भाषा में "अपवाद" शब्द से परिचित और
try
/ catch
निर्माण के सिद्धांत को समझता है; - Node.js के विकास से परिचित और अतुल्यकालिक प्रोग्रामिंग के सिद्धांतों में महारत हासिल की।
पाठक को यह समझना चाहिए कि
try
/
catch
निर्माण की उपस्थिति के बावजूद अपवाद फेंकना नीचे दिए गए कोड में काम क्यों नहीं करता है।
1 function myFunc(callback) { try { doSomeAsyncOperation(function (err) { if (err) { throw (err); } }); } catch (ex) { callback(ex); } }
पाठक को पता होना चाहिए कि Node.js में 3 मुख्य तरीके हैं जो एक समारोह में एक त्रुटि वापस कर सकते हैं:
throw
एरर फेंकना (एक अपवाद फेंकना)।- पहले तर्क के रूप में एक त्रुटि ऑब्जेक्ट के साथ कॉलबैक फ़ंक्शन को कॉल करें।
- EventEmitter वर्ग की एक वस्तु पर
'error'
घटना को उठाना।
यह माना जाता है कि पाठक Node.js. में
डोमेन से परिचित नहीं है
पाठक को जावास्क्रिप्ट में त्रुटि और अपवाद के बीच अंतर को समझना चाहिए। त्रुटि
Error
वर्ग का कोई भी ऑब्जेक्ट है। त्रुटि क्लास कंस्ट्रक्टर द्वारा बनाई जा सकती है और थ्रोस्टैमेंट स्टेटमेंट का उपयोग करके फ़ंक्शन से लौटी या फेंक दी जा सकती है। जब कोई त्रुटि ऑब्जेक्ट फेंक दिया जाता है, तो एक अपवाद फेंक दिया जाता है। निम्नलिखित त्रुटियों को फेंकने का एक उदाहरण है (अपवाद फेंकना):
2 throw new Error(' ');
एक उदाहरण जहां कॉलबैक फ़ंक्शन में त्रुटि पारित की जाती है:
callback(new Error(' '));
दूसरा विकल्प Node.js में अधिक सामान्य है, क्योंकि अधिकांश ऑपरेशनों की अतुल्यकालिकता के कारण। एक नियम के रूप में, पहले विकल्प का उपयोग केवल तब किया जाता है जब डेटा को
JSON.parse
करना (उदाहरण के लिए,
JSON.parse
), जबकि अपवाद
JSON.parse
का
try
/
catch
निर्माण का उपयोग करके पकड़ा जाता है। यह जावा या C ++ और अन्य भाषाओं से Node.js को अलग करता है, जहां आपको अपवादों से अधिक बार सामना करना पड़ता है।
2. सॉफ्टवेयर एरर और प्रोग्रामर एरर
त्रुटियों को सशर्त रूप से दो प्रकारों में विभाजित किया जा सकता है:
3- सॉफ्टवेयर त्रुटियां एक कार्यक्रम के सामान्य कामकाज के दौरान उत्पन्न होने वाली उलझनें हैं। वे "बग" नहीं हैं। आमतौर पर, वे सीधे कार्यक्रम से संबंधित नहीं होते हैं: सिस्टम त्रुटियां (उदाहरण के लिए, मेमोरी अतिप्रवाह), कॉन्फ़िगरेशन त्रुटियां (उदाहरण के लिए, दूरस्थ सर्वर का पता गलत है), इंटरनेट कनेक्शन त्रुटियां या दूरस्थ सर्वर पर हुई त्रुटियां।
सॉफ्टवेयर त्रुटियों के उदाहरण:
- उपयोगकर्ता ने गलत डेटा दर्ज किया,
- अनुरोध समय समाप्त हो गया है
- सर्वर ने कोड 500 के साथ एक त्रुटि के साथ अनुरोध का जवाब दिया,
- वियोग,
- आवंटित स्मृति का उपयोग किया जाता है।
- प्रोग्रामर त्रुटियां कोड दोष हैं जो गलत प्रोग्राम ऑपरेशन की ओर ले जाती हैं। इस प्रकार की त्रुटियों को सही ढंग से नियंत्रित नहीं किया जा सकता है, क्योंकि उनकी उपस्थिति का तथ्य लिखित कोड की गलतता को दर्शाता है। प्रोग्राम कोड को बदलकर इस प्रकार की त्रुटियों को समाप्त किया जा सकता है। प्रोग्रामर की त्रुटियों में शामिल हैं:
undefined
मूल्य के साथ एक क्षेत्र का उपयोग करने का प्रयास,- कॉलबैक फ़ंक्शन के बिना एक अतुल्यकालिक फ़ंक्शन को कॉल करना,
- अमान्य तर्कों के साथ एक फ़ंक्शन को कॉल करना।
डेवलपर्स अपने मूलभूत मतभेदों के बावजूद, दोनों प्रकार की त्रुटियों के लिए "त्रुटि" शब्द का उपयोग करते हैं। "फ़ाइल नहीं मिली" एक सॉफ़्टवेयर त्रुटि है, इसकी घटना का मतलब यह हो सकता है कि प्रोग्राम को खोजे जाने के लिए फ़ाइल बनाने की आवश्यकता है। इस प्रकार, इस त्रुटि की घटना एक गलत प्रोग्राम व्यवहार नहीं है। प्रोग्रामर त्रुटियों, इसके विपरीत, डेवलपर द्वारा प्रत्याशित नहीं किया गया था। शायद डेवलपर ने चर नाम में एक गलती की या उपयोगकर्ता द्वारा दर्ज किए गए डेटा के सत्यापन को गलत तरीके से वर्णित किया। इस प्रकार की त्रुटि को नियंत्रित नहीं किया जा सकता है।
ऐसे मामले हो सकते हैं, जब एक ही कारण से, प्रोग्राम त्रुटि और प्रोग्रामर त्रुटि दोनों हो। मान लीजिए कि एक HTTP सर्वर एक
undefined
मूल्य से एक फ़ील्ड को पढ़ने का प्रयास करता है, जो एक प्रोग्रामर त्रुटि है। नतीजतन, सर्वर क्रैश हो जाता है। क्लाइंट, उसी समय,
ECONNRESET
त्रुटि प्राप्त करता है, जिसे आमतौर पर Node.js द्वारा वर्णित किया जाता है: "सॉकेट हैंग-अप", इसके अनुरोध के जवाब में। क्लाइंट के लिए, यह एक सॉफ्टवेयर त्रुटि है और एक सही ढंग से लिखा गया क्लाइंट प्रोग्राम तदनुसार त्रुटि को संसाधित करेगा और काम करना जारी रखेगा।
प्रोग्राम एरर हैंडलर की अनुपस्थिति एक प्रोग्रामर एरर है। मान लें कि क्लाइंट प्रोग्राम, सर्वर के साथ कनेक्शन स्थापित करते समय, एक ECONNREFUSED त्रुटि का सामना करता है, परिणामस्वरूप, कनेक्शन ऑब्जेक्ट
'error'
घटना उत्पन्न करता है, लेकिन इस घटना के लिए कोई हैंडलर फ़ंक्शन पंजीकृत नहीं हैं, इस कारण से प्रोग्राम क्रैश हो जाता है। इस स्थिति में, कनेक्शन त्रुटि एक सॉफ़्टवेयर त्रुटि है, हालांकि, कनेक्शन ऑब्जेक्ट 'त्रुटि' ईवेंट के लिए हैंडलर की अनुपस्थिति एक प्रोग्रामर त्रुटि है।
प्रोग्रामर त्रुटियों और प्रोग्राम त्रुटियों के बीच अंतर को समझना महत्वपूर्ण है। इसलिए, लेख को पढ़ना जारी रखने से पहले, सुनिश्चित करें कि आप इन अवधारणाओं को समझते हैं।
सॉफ्टवेयर एरर हैंडलिंग
प्रोग्राम त्रुटियों की प्रक्रिया, साथ ही सुरक्षा या अनुप्रयोग प्रदर्शन के मुद्दे, किसी भी मॉड्यूल के परिचय से हल किए जा सकने वाले कार्यों के प्रकार से संबंधित नहीं होते हैं - स्रोत कोड के एक स्थान पर त्रुटि से जुड़ी सभी समस्याओं को हल करना असंभव है। त्रुटि से निपटने की समस्या को हल करने के लिए एक विकेंद्रीकृत दृष्टिकोण की आवश्यकता होती है। कार्यक्रम के सभी वर्गों के लिए जहां एक त्रुटि संभव है (फ़ाइल सिस्टम तक पहुंच, एक दूरस्थ सर्वर से कनेक्शन, एक बच्चे की प्रक्रिया बनाना, आदि), प्रत्येक संभावित प्रकार की त्रुटि के लिए उपयुक्त प्रसंस्करण स्क्रिप्ट को लिखना आवश्यक है। इसका मतलब यह है कि न केवल समस्या क्षेत्रों को उजागर करना आवश्यक है, बल्कि यह भी समझना है कि उनमें किस प्रकार की त्रुटियां उत्पन्न हो सकती हैं।
कुछ मामलों में, त्रुटि ऑब्जेक्ट को उस फ़ंक्शन से स्थानांतरित करना आवश्यक है जिसमें यह कॉलबैक फ़ंक्शन के माध्यम से उच्च स्तर तक हुआ था, और इससे भी उच्चतर, इसलिए त्रुटि "पॉप अप" होती है जब तक कि यह उस एप्लिकेशन के तार्किक स्तर तक नहीं पहुंचता जो प्रसंस्करण के लिए जिम्मेदार है इस प्रकार की त्रुटि। एक जिम्मेदार स्तर पर, कार्यक्रम यह तय कर सकता है कि क्या समस्या संचालन को फिर से शुरू करना है, उपयोगकर्ता को त्रुटि की रिपोर्ट करें, या किसी लॉग फ़ाइल में त्रुटि के बारे में जानकारी लिखें, आदि। आपको हमेशा इस योजना पर भरोसा नहीं करना चाहिए और कॉलबैक के बाद से पदानुक्रम के उच्च स्तर तक त्रुटियों को पारित करना चाहिए- उच्च स्तर पर कार्य उस संदर्भ के बारे में कुछ भी नहीं जानते हैं जिसमें त्रुटि उनके पास हुई। नतीजतन, एक स्थिति उत्पन्न हो सकती है जब चयनित तार्किक स्तर पर हुई त्रुटि के अनुरूप प्रसंस्करण तर्क का वर्णन करना मुश्किल होगा।
हम परिदृश्यों को संभालने में संभावित त्रुटि को उजागर करते हैं:
- इस त्रुटि को ठीक करने के लिए। कभी-कभी, एक त्रुटि को समाप्त किया जा सकता है। मान लीजिए कि किसी लॉग फ़ाइल में जानकारी लिखने का प्रयास करते समय कोई त्रुटि हुई। इसका मतलब यह हो सकता है कि कार्यक्रम पहली बार चल रहा है और लॉग फ़ाइल अभी तक नहीं बनाई गई है। इस मामले में, हैंडलर वांछित फ़ाइल बनाकर त्रुटि को समाप्त कर सकता है। यहां एक और दिलचस्प उदाहरण है: कार्यक्रम को लगातार एक निश्चित उत्तर (उदाहरण के लिए, डेटाबेस के साथ) के साथ संबंध बनाए रखने की आवश्यकता होती है, लेकिन काम के दौरान एक वियोग था। इस स्थिति में, त्रुटि हैंडलर डेटाबेस को पुन: कनेक्ट कर सकता है।
- उपयोगकर्ता को सूचित करना और अनुरोध के प्रसंस्करण को समाप्त करना। यदि समस्या को हल करना संभव नहीं है, तो वर्तमान ऑपरेशन को बाधित करना और उपयोगकर्ता को त्रुटि के बारे में सूचित करना सबसे आसान है। यह परिदृश्य उन मामलों में लागू होता है जहां यह ज्ञात है कि त्रुटि का कारण समय के साथ गायब नहीं होता है। उदाहरण के लिए, यदि क्लाइंट द्वारा प्रेषित JSON डेटा को डीरियलाइज़ करने का प्रयास करते समय कोई त्रुटि हुई है, तो उसी डेटा के साथ फिर से प्रयास करने का कोई मतलब नहीं है।
- बार-बार ऑपरेशन। नेटवर्क से संबंधित त्रुटियों की स्थिति में, ऑपरेशन को फिर से शुरू करने से मदद मिल सकती है। मान लीजिए, किसी दूरस्थ सेवा के अनुरोध के जवाब में, प्रोग्राम को प्रतिक्रिया में 503 (सेवा अनुपलब्ध त्रुटि) प्राप्त हुई, इस स्थिति में यह कुछ सेकंड के बाद अनुरोध को दोहराने के लायक हो सकता है। दोहराव की अंतिम संख्या निर्धारित करना महत्वपूर्ण है, साथ ही कितनी बार प्रयास किए जाने चाहिए। लेकिन आपको हमेशा इस परिदृश्य पर भरोसा नहीं करना चाहिए। मान लीजिए कि एक उपयोगकर्ता कुछ सेवा के लिए एक अनुरोध को पूरा करता है जिसे अनुरोध को संसाधित करने के लिए आपके प्रोग्राम तक पहुंचने की आवश्यकता होती है, और आपका कार्यक्रम बदले में, किसी अन्य सेवा से अनुरोध करता है जो त्रुटि 503 के साथ प्रतिक्रिया करता है। इस मामले में, सबसे अच्छा समाधान फिर से कोशिश नहीं करना होगा। , और तुरंत उस मूल सेवा में त्रुटि को संसाधित करने का अवसर दें जिसके साथ उपयोगकर्ता काम कर रहा है। यदि अनुरोध श्रृंखला में भाग लेने वाली प्रत्येक सेवा बार-बार प्रयास करेगी, तो उपयोगकर्ता अपने अनुरोध के जवाब की प्रतीक्षा करेगा यदि वह मूल सेवा द्वारा केवल प्रदर्शन किया गया हो।
- कार्यक्रम समाप्ति। यदि कोई अप्रत्याशित स्थिति उत्पन्न होती है, तो उसका प्रकट होना कार्यक्रम के सामान्य कामकाज के दौरान असंभव है, तो आपको संबंधित लॉग फ़ाइल में त्रुटि जानकारी लिखनी चाहिए और काम करना बंद कर देना चाहिए। इस स्क्रिप्ट का उपयोग किया जा सकता है यदि आपका प्रोग्राम उपलब्ध मेमोरी से बाहर चला गया है (हालाँकि, यदि आपके प्रोग्राम को चाइल्ड प्रोसेस से ENOMEM त्रुटि मिली है, तो आप त्रुटि को संसाधित कर सकते हैं और प्रोग्राम को रोक नहीं सकते हैं)। साथ ही, इस परिदृश्य को लागू किया जा सकता है यदि आपके प्रोग्राम में काम के लिए आवश्यक फ़ाइलों तक पहुँच अधिकार नहीं है।
- लॉग फ़ाइल में त्रुटि लिखना और जारी रखना। कुछ मामलों में, प्रोग्राम को समाप्त करने के लिए आवश्यक नहीं है, भले ही जो त्रुटि होती है वह अपरिवर्तनीय है। एक उदाहरण वह स्थिति है जब आपका कार्यक्रम समय-समय पर DNS सिस्टम के माध्यम से दूरस्थ सेवाओं के एक समूह तक पहुंचता है, और सेवाओं में से एक DNS के "बाहर चला जाता है"। इस स्थिति में, कार्यक्रम शेष सेवाओं के साथ काम करना जारी रख सकता है। लेकिन, फिर भी, लॉग फ़ाइल में त्रुटि के बारे में लिखना आवश्यक है। (किसी नियम के लिए हमेशा अपवाद होते हैं, यदि कोई त्रुटि प्रति सेकंड एक हजार बार होती है, और आप इसके बारे में कुछ भी नहीं कर सकते हैं, तो आपको हर बार लॉग को लिखने की आवश्यकता नहीं है, हालांकि, यह समय-समय पर लॉगिंग के लायक है।)
प्रोग्रामर त्रुटि से निपटने
प्रोग्रामर त्रुटियों को संभालने का कोई सही तरीका नहीं है। परिभाषा के अनुसार, यदि ऐसी त्रुटि होती है, तो प्रोग्राम कोड गलत है। आप केवल कोड को ठीक करके समस्या को ठीक कर सकते हैं।
ऐसे प्रोग्रामर हैं जो मानते हैं कि कुछ मामलों में इस तरह से त्रुटि के बाद कार्यक्रम को पुनर्स्थापित करना संभव है, जिससे वर्तमान संचालन बाधित हो, लेकिन कार्यक्रम, फिर भी, काम करना जारी रखता है और अन्य अनुरोधों को संसाधित करता है। यह अनुशंसित नहीं है। इस तथ्य को ध्यान में रखते हुए कि एक प्रोग्रामर की त्रुटि कार्यक्रम को अस्थिर स्थिति में पेश करती है, क्या आप सुनिश्चित कर सकते हैं कि त्रुटि अन्य अनुरोधों के संचालन में हस्तक्षेप नहीं करेगी? यदि अनुरोध समान संस्थाओं (उदाहरण के लिए, सर्वर, सॉकेट, डेटाबेस कनेक्शन, आदि) के साथ काम करते हैं, तो यह केवल इस आशा के साथ रहता है कि बाद के अनुरोधों को सही तरीके से संसाधित किया जाएगा।
REST सेवा पर विचार करें (उदाहरण के लिए,
पुनर्स्थापना मॉड्यूल का उपयोग करके कार्यान्वित)। मान लीजिए कि अनुरोध संचालकों में से
RefferenceError
अपवाद
RefferenceError
है क्योंकि प्रोग्रामर ने चर नाम में एक टाइपो बनाया है। यदि आप तुरंत सेवा बंद नहीं करते हैं, तो कई समस्याएं उत्पन्न हो सकती हैं, जिन्हें ट्रैक करना मुश्किल हो सकता है:
- यदि टाइपो के परिणामस्वरूप कुछ इकाई
null
या undefined
, तो बाद के अनुरोध, इसे बदलकर, अपवाद भी फेंक देंगे और संसाधित नहीं किए जाएंगे। - यदि अपवाद को फेंकने वाले फ़ंक्शन ने डेटाबेस के साथ काम किया, तो कनेक्शन रिसाव हो सकता है। जितनी बार एक समान त्रुटि दोहराई जाती है, उतने कनेक्शन की संख्या, जिनके उपयोग से सेवा डेटाबेस के साथ काम कर सकती है, घट जाएगी।
- अधिक जटिल स्थिति हो सकती है यदि पोस्टग्रेज को डेटाबेस के रूप में उपयोग किया जाता है, और लेनदेन के दौरान कनेक्शन बंद रहता है। इस मामले में, "लटका हुआ" लेनदेन आपको पुराने रिकॉर्ड के पुराने संस्करणों को साफ़ करने की अनुमति नहीं देगा जो इसे दिखाई दे रहे हैं। एक लेनदेन सप्ताह के लिए खुला रह सकता है। स्मृति में तालिका का आकार आकार प्रतिबंधों के बिना बढ़ेगा, जो इस तथ्य को जन्म देगा कि बाद के प्रश्नों का प्रसंस्करण धीमा हो जाएगा। 4 , निश्चित रूप से, यह उदाहरण काफी विशिष्ट है और केवल पोस्टग्रेज पर लागू होता है, हालांकि, यह पूरी तरह से दिखाता है कि यह एक प्रोग्राम के साथ काम करना जारी रखना खतरनाक है जो एक अस्थिर स्थिति में है।
- दूरस्थ सेवा के लिए कनेक्शन अस्पष्ट रह सकता है, जिसके परिणामस्वरूप अगले अनुरोध को गलत उपयोगकर्ता की ओर से संसाधित किया जा सकता है।
- सॉकेट अशुद्ध हो सकता है। डिफ़ॉल्ट रूप से, Node.js दो मिनट में निष्क्रिय सॉकेट को बंद कर देगा, लेकिन इस व्यवहार को ओवरराइड किया जा सकता है, और यदि त्रुटि दोहराई जाती है, तो अंत में संभावित सॉकेट की संख्या समाप्त हो जाएगी। यदि आप डिफ़ॉल्ट कॉन्फ़िगरेशन छोड़ देते हैं, तो समस्या को ट्रैक करना और ठीक करना मुश्किल होगा, क्योंकि दो मिनट की देरी के साथ एक निष्क्रिय सॉकेट त्रुटि होती है।
- एक स्मृति रिसाव हो सकती है, जो कार्यक्रम के अतिप्रवाह और दुर्घटनाओं को जन्म देगी। या इससे भी बदतर - एक रिसाव कचरा संग्रह प्रक्रिया को जटिल कर सकता है, जिससे कार्यक्रम के प्रदर्शन को नुकसान होगा। इस मामले में समस्या का कारण खोजना विशेष रूप से कठिन होगा।
उपरोक्त को देखते हुए, ऐसी स्थितियों में, कार्यक्रम को बाधित करने का सबसे अच्छा समाधान है। बाधित होने के बाद आप अपने कार्यक्रम को फिर से शुरू कर सकते हैं - यह दृष्टिकोण त्रुटियों के होने के बाद आपकी सेवा के स्थिर संचालन को स्वचालित रूप से पुनर्स्थापित करेगा।
इस दृष्टिकोण का एकमात्र, लेकिन महत्वपूर्ण, दोष यह है कि पुनरारंभ के समय सेवा के साथ काम करने वाले सभी उपयोगकर्ता काट दिए जाएंगे। निम्नलिखित बातों का ध्यान रखें:
- प्रोग्रामर त्रुटि के कारण विफलता ने एप्लिकेशन को अस्थिर स्थिति में डाल दिया। यह सुनिश्चित करने के लिए प्रयास करना आवश्यक है कि ऐसी त्रुटियां उत्पन्न न हों, उनके उन्मूलन की सर्वोच्च प्राथमिकता है।
- पुनरारंभ करने के बाद, अनुरोध दोनों को सही तरीके से निष्पादित किया जा सकता है, और फिर से एक त्रुटि हो सकती है। ऐसा हो सकता है कि अनुरोधों को सही तरीके से संसाधित नहीं किया गया है, लेकिन समस्या को ट्रैक करना मुश्किल है।
- एक अच्छी तरह से डिज़ाइन की गई प्रणाली में, भले ही त्रुटि इंटरनेट कनेक्शन की समस्या के कारण हुई हो या यदि Node.js में त्रुटि हुई हो, क्लाइंट प्रोग्राम को सर्वर त्रुटियों को संभालने में सक्षम होना चाहिए (पुन: कनेक्ट करें, बार-बार अनुरोध करें)।
यदि प्रोग्राम को बहुत बार पुनरारंभ किया जाता है, तो आपको कोड को डीबग करना चाहिए और त्रुटियों को ठीक करना चाहिए। डीबग करने का सबसे अच्छा तरीका
कर्नेल स्नैपशॉट को
सहेजना और विश्लेषण करना है । यह दृष्टिकोण जीएनयू / लिनक्स सिस्टम और इल्यूमोस सिस्टम दोनों में काम करता है, और आपको न केवल उन कार्यों के अनुक्रम को देखने की अनुमति देता है जो त्रुटि का कारण बने, बल्कि तर्कों के साथ-साथ क्लोजर के माध्यम से दिखाई देने वाली अन्य वस्तुओं की स्थिति भी।
3. समारोह लेखन पैटर्न
सबसे पहले, यह ध्यान देने योग्य है कि अपने कार्यों को विस्तार से दस्तावेज करना बहुत महत्वपूर्ण है। यह बताना आवश्यक है कि फ़ंक्शन क्या देता है, फ़ंक्शन के निष्पादन के दौरान यह क्या तर्क देता है और क्या त्रुटियां हो सकती हैं। जब तक आप संभावित त्रुटियों के प्रकारों का निर्धारण नहीं करते हैं और उनका मतलब क्या है, तब तक आप सही तरीके से हैंडलर नहीं लिख पाएंगे।
फेंक, कॉलबैक या EventEmitter?
किसी फ़ंक्शन से त्रुटि वापस करने के तीन मुख्य तरीके हैं:
- तुल्यकालन में एक त्रुटि देता है। इसका मतलब यह है कि अपवाद उसी संदर्भ में होगा जिसमें फ़ंक्शन को बुलाया गया था। यदि कोशिश / पकड़ का उपयोग किया जाता है, तो अपवाद पकड़ा जाएगा। अन्यथा, कार्यक्रम विफल हो जाएगा (जब तक, निश्चित रूप से, अपवाद डोमेन को पकड़ता है या वैश्विक प्रक्रिया ऑब्जेक्ट के
'uncaughtException'
ईवेंट हैंडलर, इस विकल्प को बाद में माना जाएगा)। - पहले तर्क के रूप में एक त्रुटि ऑब्जेक्ट के साथ कॉलबैक फ़ंक्शन को कॉल करना एक अतुल्यकालिक फ़ंक्शन से त्रुटि को वापस करने के लिए सबसे अधिक उपयोग किया जाने वाला तरीका है। कॉलबैक फ़ंक्शन को कॉल करने के लिए एक सामान्य पैटर्न फॉर्म
callback(err, results)
की कॉल है, जहां केवल एक तर्क null
से भिन्न मान ले सकता है। - अधिक जटिल मामलों में, फ़ंक्शन EventEmitter वर्ग
'error'
वस्तु की घटना 'error'
उत्पन्न कर सकता है, फिर त्रुटि को संसाधित किया जाएगा यदि कोई हैंडलर घटना 'error'
लिए पंजीकृत है। इस विकल्प का उपयोग किया जाता है यदि:
- एक जटिल ऑपरेशन किया जाता है जो कई परिणाम या त्रुटियां देता है। एक उदाहरण एक डेटाबेस से रिकॉर्ड प्राप्त होगा। फ़ंक्शन EventEmitter वर्ग की एक वस्तु लौटाता है और जब प्रत्येक रिकॉर्ड को पुनर्प्राप्त किया जाता है, तो
"end"
'row'
इवेंट को उठाता है, जब सभी रिकॉर्ड पुनर्प्राप्त किए जाते हैं, तो "end"
और यदि कोई त्रुटि होती है, तो 'error'
। - ऑब्जेक्ट एक जटिल ऑटोमेटोन है जो कई अतुल्यकालिक संचालन करता है। एक उदाहरण सॉकेट, जिससे घटनाओं है
'connect'
, 'end'
, 'timeout'
, 'drain'
और 'close'
। यदि कोई त्रुटि होती है, तो ऑब्जेक्ट एक घटना उत्पन्न करेगा 'error'
। इस दृष्टिकोण का उपयोग करना, यह समझना महत्वपूर्ण है कि किन स्थितियों में त्रुटि हो सकती है, क्या इस मामले में अन्य घटनाएं हो सकती हैं, और वे किस क्रम में हो सकते हैं।
कॉलबैक फ़ंक्शंस का उपयोग करना और घटनाओं को उत्पन्न करना त्रुटियों को वापस करने के लिए अतुल्यकालिक तरीकों में से एक है। यदि एक अतुल्यकालिक ऑपरेशन किया जाता है, तो इन विधियों में से एक को लागू किया जाता है, लेकिन दोनों का उपयोग कभी भी नहीं किया जाता है।तो, फेंक का उपयोग कब करें, और कॉलबैक फ़ंक्शन या घटनाओं का उपयोग कब करें? यह दो कारकों पर निर्भर करता है:- त्रुटि का प्रकार (प्रोग्रामर त्रुटि या सॉफ़्टवेयर त्रुटि),
- फ़ंक्शन का प्रकार जिसमें त्रुटि हुई (एसिंक्रोनस या सिंक्रोनस)।
अतुल्यकालिक कार्यों के लिए सॉफ़्टवेयर त्रुटियाँ अधिक सामान्य हैं। असिंक्रोनस फ़ंक्शन एक कॉलबैक फ़ंक्शन को एक तर्क के रूप में लेते हैं; जब कोई त्रुटि होती है, तो इसे त्रुटि ऑब्जेक्ट के साथ तर्क के रूप में कहा जाता है। यह दृष्टिकोण खुद को साबित कर चुका है और व्यापक रूप से उपयोग किया जाता है। एक उदाहरण Node.js मॉड्यूल है fs
। घटना दृष्टिकोण का भी उपयोग किया जाता है, लेकिन पहले से ही अधिक जटिल मामलों में।समकालिक कार्यों में सॉफ़्टवेयर त्रुटियां एक नियम के रूप में हो सकती हैं, यदि फ़ंक्शन उपयोगकर्ता द्वारा दर्ज किए गए डेटा के साथ काम करता है (उदाहरण के लिए, JSON.parat)। ऐसे कार्यों में, एक त्रुटि तब होती है जब एक त्रुटि होती है, कम बार, त्रुटि वस्तु रिटर्न स्टेटमेंट द्वारा वापस आ जाती है।यदि फ़ंक्शन में संभावित त्रुटियों में से कम से कम एक अतुल्यकालिक है, तो सभी संभावित त्रुटियों को एसिंक्रोनस दृष्टिकोण का उपयोग करके फ़ंक्शन से वापस किया जाना चाहिए। भले ही त्रुटि उसी संदर्भ में हुई हो जिसमें फ़ंक्शन को कॉल किया गया था, त्रुटि ऑब्जेक्ट को एसिंक्रोनस रूप से वापस किया जाना चाहिए।एक महत्वपूर्ण नियम है: एक ही फ़ंक्शन में त्रुटियों को वापस करने के लिए, या तो एक तुल्यकालिक या अतुल्यकालिक दृष्टिकोण को लागू किया जा सकता है, लेकिन दोनों कभी नहीं । फिर, एक फ़ंक्शन त्रुटि को स्वीकार करने के लिए, आपको कॉलबैक फ़ंक्शन (या इवेंट हैंडलर फ़ंक्शन 'error'
), या कोशिश / कैच निर्माण का उपयोग करने की आवश्यकता होगी , लेकिन दोनों कभी नहीं। फ़ंक्शन के लिए प्रलेखन को यह इंगित करना चाहिए कि इसके लिए कौन सी विधि लागू है।इनपुट तर्कों की जाँच करना आमतौर पर आपको कई त्रुटियों को रोकने की अनुमति देता है जो प्रोग्रामर बनाते हैं। अक्सर ऐसा होता है कि जब आप एक एसिंक्रोनस फ़ंक्शन को कॉल करते हैं, तो वे कॉलबैक फ़ंक्शन को पास करना भूल जाते हैं, परिणामस्वरूप, यह समझने के लिए कि त्रुटि कहां होती है, डेवलपर को कम से कम कॉल किए गए फ़ंक्शन के ढेर को देखना होगा। इसलिए, यदि फ़ंक्शन असिंक्रोनस है, तो सबसे पहले, यह जांचना महत्वपूर्ण है कि कॉलबैक फ़ंक्शन पास हुआ है या नहीं। यदि पारित नहीं हुआ है, तो एक अपवाद फेंक दिया जाना चाहिए। इसके अलावा, एक फ़ंक्शन की शुरुआत में, आपको इसे पारित किए गए प्रकार के तर्कों की जांच करनी चाहिए, और यदि वे गलत हैं तो एक अपवाद फेंक दें।याद रखें कि प्रोग्रामर त्रुटियां सामान्य प्रोग्राम प्रक्रिया का हिस्सा नहीं हैं। उन्हें पकड़ा और संसाधित नहीं किया जाना चाहिए। इसलिए, प्रोग्रामर त्रुटियों के लिए अपवादों को तत्काल फेंकने पर ये सिफारिशें ऊपर तैयार किए गए नियम का खंडन नहीं करती हैं कि एक ही फ़ंक्शन त्रुटियों को वापस करने के लिए एक तुल्यकालिक और अतुल्यकालिक दृष्टिकोण दोनों को लागू नहीं करना चाहिए।मानी गई सिफारिशें तालिका में प्रस्तुत की गई हैं:उदाहरण उदाहरण | प्रकार प्रकार | त्रुटि | त्रुटि का प्रकार | कैसे लौटेंगे? | कैसे संभालना है |
fs.stat | अतुल्यकालिक | फ़ाइल नहीं मिली | सॉफ्टवेयर | कॉलबैक | हैंडलर समारोह |
JSON.parse | एक समय का | इनपुट त्रुटि | सॉफ्टवेयर | throw | try / catch |
fs.stat | अतुल्यकालिक | आवश्यक तर्क गायब है | प्रोग्रामर त्रुटि | throw | संसाधित नहीं किया गया (कार्य समाप्ति) |
पहली प्रविष्टि सबसे आम उदाहरण प्रस्तुत करती है - एक एसिंक्रोनस फ़ंक्शन। दूसरी पंक्ति एक तुल्यकालिक फ़ंक्शन के लिए एक उदाहरण है, यह विकल्प कम सामान्य है। तीसरी पंक्ति में प्रोग्रामर की त्रुटि है; यह वांछनीय है कि ऐसे मामले केवल कार्यक्रम के विकास के दौरान होते हैं।इनपुट त्रुटि: प्रोग्रामर त्रुटि या सॉफ्टवेयर त्रुटि?
प्रोग्राम त्रुटियों से प्रोग्रामर त्रुटियों को कैसे भेद करें? यह आपको तय करना है कि स्थानांतरित किए गए कार्य कौन से डेटा सही हैं और कौन से नहीं। यदि आपकी आवश्यकताओं को पूरा नहीं करने वाले तर्क फ़ंक्शन को दिए जाते हैं, तो यह एक प्रोग्रामर त्रुटि है। यदि तर्क सही हैं, लेकिन फ़ंक्शन उनके साथ काम नहीं कर सकता है, तो यह एक सॉफ्टवेयर त्रुटि है।आपको यह तय करना होगा कि तर्कों को जाँचने के लिए कौन सी कठोरता है। एक फ़ंक्शन की कल्पना करें जो connect
एक आईपी पते और कॉलबैक फ़ंक्शन को तर्क के रूप में लेता है। मान लीजिए कि यह फ़ंक्शन एक तर्क के साथ बुलाया गया था जो आईपी पते से प्रारूप में भिन्न होता है, उदाहरण के लिए: "बॉब"। विचार करें कि इस मामले में क्या हो सकता है:- , IPv4 , . .
- , , IP- «bob».
दोनों विकल्प समीक्षा की गई सिफारिशों को पूरा करते हैं, और यह आप पर निर्भर है कि कितनी सख्ती से जाँच करनी है। उदाहरण के लिए, Date.parse फ़ंक्शन विभिन्न प्रारूपों के तर्क स्वीकार करता है, लेकिन अच्छे कारण के लिए। फिर भी, अधिकांश कार्यों के लिए, पारित किए गए तर्कों की सख्ती से जांच करने की सिफारिश की जाती है। तर्कों की जाँच के लिए जितना अधिक अस्पष्ट हो, उतनी ही कठिन प्रक्रिया डिबगिंग कोड बन जाती है। एक नियम के रूप में, परीक्षण सख्त, बेहतर। और यहां तक कि अगर प्रोग्राम के भविष्य के संस्करणों में आप अचानक किसी फ़ंक्शन के अंदर जांच के मानदंड को नरम करते हैं, तो आप अपने कोड को तोड़ने का जोखिम नहीं उठाते हैं।यदि हस्तांतरित मूल्य आवश्यकताओं को पूरा नहीं करता है (उदाहरण के लिए,undefined
या स्ट्रिंग में गलत प्रारूप है), तो फ़ंक्शन को रिपोर्ट करना चाहिए कि पारित मूल्य गलत है और कार्यक्रम बंद कर दें। गलत तर्कों की रिपोर्ट करके कार्यक्रम को रोककर, आप अपने और अन्य प्रोग्रामर के लिए कोड डीबग करने की प्रक्रिया को सरल बनाते हैं।डोमेन और process.on ('uncaughtException')
सॉफ़्टवेयर त्रुटियों को हमेशा एक विशिष्ट तंत्र का उपयोग करके पकड़ा जा सकता है: कॉलबैक फ़ंक्शन या इवेंट हैंडलर में try
/ के माध्यम से । एक वैश्विक वस्तु के डोमेन और घटनाओं को अक्सर अप्रत्याशित त्रुटियों के खिलाफ पुनर्बीमा के लिए उपयोग किया जाता है जो एक प्रोग्रामर बना सकता है। उपरोक्त विचारों को देखते हुए, इस दृष्टिकोण को दृढ़ता से हतोत्साहित किया जाता है।catch
'error'
process
'uncaughtException'
4. लेखन कार्य के लिए नियम
कार्य लिखते समय, इन दिशानिर्देशों का पालन करें:
. :
- , .
:
- Error ( ) .
Error , . name
message
, stack
.
- , .
, propertyName propertyValue. remoteIp, . syscall
, , , errno
, . .
:
name
: .message
: . , , .stack
: . V8 , , .
, , message . , .
- , .
, , , callback- , , , . «». . verror .
fetchConfig
, . fetchConfig
. .
1.
1.1
1.1.1 DNS
1.1.2 TCP
1.1.3
1.2।
1.3।
1.4.
2.
, 1.1.2 . fetchConfig
, :
myserver: Error: connect ECONNREFUSED
.
, :
myserver: failed to start up: failed to load configuration: failed to connect to database server: failed to connect to 127.0.0.1 port 1234: connect ECONNREFUSED
, :
myserver: failed to load configuration: connection refused from database at 127.0.0.1 port 1234.
, , — .
, :
- , .
name
, . , , , .message
रैपिंग के दौरान फ़ील्ड को भी बदला जा सकता है, लेकिन आपको मूल ऑब्जेक्ट का संदेश नहीं बदलना चाहिए। फ़ील्ड के साथ कोई क्रिया न करें stack
, जैसा कि ऊपर उल्लेख किया गया है, V8 stack
इसे एक्सेस करते समय केवल एक ऑब्जेक्ट बनाता है, और यह एक काफी संसाधन-गहन प्रक्रिया है जो आपके प्रोग्राम के प्रदर्शन में महत्वपूर्ण कमी ला सकती है।
जॉयंट में , हम त्रुटियों को लपेटने के लिए verror मॉड्यूल का उपयोग करते हैं, क्योंकि इसमें न्यूनतम सिंटैक्स होता है। लेखन के समय, कुछ सिफारिशों को मॉड्यूल में लागू नहीं किया गया है, लेकिन इसे अंतिम रूप दिया जाएगा।
5. उदाहरण
उदाहरण के लिए, एक फ़ंक्शन जो एक निर्दिष्ट IPv4 पते पर एक टीसीपी कनेक्शन बनाता है। function connect(ip4addr, tcpPort, timeout, callback) { assert.equal(typeof (ip4addr), 'string', " 'ip4addr' "); assert.ok(net.isIPv4(ip4addr), " 'ip4addr' IPv4 "); assert.equal(typeof (tcpPort), 'number', " 'tcpPort' "); assert.ok(!isNaN(tcpPort) && tcpPort > 0 && tcpPort < 65536, " 'tcpPort' 1 65535"); assert.equal(typeof (timeout), 'number', " 'timeout' "); assert.ok(!isNaN(timeout) && timeout > 0, " 'timeout' "); assert.equal(typeof (callback), 'function'); }
यह उदाहरण काफी आदिम है, लेकिन यह कई सिफारिशों को दर्शाता है:- तर्क, उनके प्रकार, और उनके लिए आवश्यकताओं को विस्तार से प्रलेखित किया गया है।
- यह फ़ंक्शन उसके पास गए तर्कों की जाँच करता है और यदि अपवाद मानदंडों को पूरा नहीं करते हैं तो एक अपवाद को फेंक देता है।
- संभावित त्रुटियों के प्रकारों को प्रलेखित किया जाता है, साथ ही साथ उन क्षेत्रों को भी शामिल किया जाता है जिनमें वे शामिल हैं।
- वह विधि जिसके द्वारा फ़ंक्शन त्रुटि देता है, इंगित किया जाता है।
- लौटी त्रुटियों में "रिमोटआईपी" और "रिमोटपोर्ट" फ़ील्ड हैं, जो प्रोसेसर को इस जानकारी के आधार पर एक त्रुटि संदेश उत्पन्न करने की अनुमति देगा।
- एक त्रुटि होने के बाद कनेक्शन की स्थिति का दस्तावेजीकरण किया जाता है: "एक त्रुटि होने के बाद, फ़ंक्शन द्वारा खोले गए सॉकेट बंद हो जाएंगे।"
ऐसा प्रतीत हो सकता है कि प्रस्तुत उदाहरण में बहुत सारे अनावश्यक काम किए गए हैं, हालांकि, लेखन दस्तावेज पर खर्च किए गए दस मिनट आपके या अन्य डेवलपर्स के लिए कई घंटे बचा सकते हैं।6. सारांश
- प्रोग्रामर त्रुटियों और प्रोग्राम त्रुटियों के बीच अंतर।
- , . , .
- (,
throw
) (callback- ), . , , , callback-, try/catch, . - कार्य लिखते समय, तर्कों, उनके प्रकारों, उन पर लगाई गई आवश्यकताओं के साथ-साथ संभावित त्रुटियों के प्रकार और फ़ंक्शन कैसे त्रुटियों (तुल्यकालिक रूप से, का उपयोग कर
throw
, या अतुल्यकालिक रूप से, कॉलबैक फ़ंक्शन या ईवेंट दृष्टिकोण का उपयोग करके) का विवरण देता है। - दी गई त्रुटि त्रुटि वर्ग या व्युत्पन्न वर्ग की वस्तु होनी चाहिए। ऑब्जेक्ट में आवश्यक त्रुटि जानकारी शामिल करने के लिए नए फ़ील्ड के साथ त्रुटि ऑब्जेक्ट का विस्तार करें। यदि संभव हो, तो एप्लिकेशन में दिए गए सामान्य फ़ील्ड नामों का उपयोग करें।
7. परिशिष्ट: सामान्य त्रुटि फ़ील्ड नाम
यह दृढ़ता से अनुशंसा की जाती है कि तालिका में दिए गए फ़ील्ड नामों का उपयोग त्रुटि वस्तुओं का विस्तार करने के लिए किया जाए। प्रस्तुत नाम मानक Node.js मॉड्यूल में उपयोग किए जाते हैं, उन्हें त्रुटि संचालकों में उपयोग किया जाना चाहिए, साथ ही त्रुटि संदेश उत्पन्न करते समय भी। | |
localHostname | DNS- (, , ) |
localIp | IP- (, , ) |
localPort | TCP (, , ) |
remoteHostname | DNS- (, , ) |
remoteIp | IP- (, , ) |
remotePort | (, , ) |
path | , (IPC-) (, , ) |
srcpath | (, ) |
dstpath | (, ) |
hostname | DNS (, , IP-) |
ip | IP- (, , DNS-) |
propertyName | (, , ) |
propertyValue | (, , ) |
syscall | |
errno | errno (, "ENOENT" ) |
1 शुरुआती अक्सर एक ही गलती करते हैं। इस उदाहरण में, try
/ catch
और अपवाद को फेंकने वाले फ़ंक्शन कॉल को अतुल्यकालिक फ़ंक्शन के कारण विभिन्न संदर्भों में निष्पादित किया जाएगा doSomeAsyncOperation
, इसलिए, अपवाद नहीं पकड़ा जाएगा।2 जावास्क्रिप्ट में, यह throw
अन्य प्रकारों के मूल्यों के साथ काम कर सकता है, लेकिन यह त्रुटि वर्ग की वस्तुओं का उपयोग करने के लिए अनुशंसित है। यदि थ्रोस्टैटेमेंट में अन्य मानों का उपयोग किया जाता है, तो कॉल स्टैक प्राप्त करना असंभव होगा, जिसके कारण त्रुटि हुई, जो कोड डीबगिंग को जटिल करेगा।3 ये अवधारणाएँ Node.js. के आगमन से बहुत पहले उत्पन्न हुईं जावा में, चेक किए गए और अनियंत्रित अपवादों को अनुरूप माना जा सकता है। सी में, प्रोग्रामर त्रुटियों के साथ काम करने के लिए बयान दिए जाते हैं ।4 उपरोक्त उदाहरण बहुत ही ठोस लग सकता है, यह इसलिए है क्योंकि यह काल्पनिक नहीं है, हम वास्तव में इस समस्या में भाग गए, यह अप्रिय था।