जावास्क्रिप्ट में पकड़ने की कोशिश ... यह एक अच्छा अभ्यास नहीं है?


69

जावास्क्रिप्ट में ट्राई-कैच ब्लॉक का प्रावधान है । जावा या किसी अन्य भाषा में त्रुटि से निपटने के लिए अनिवार्य है, मैं किसी को भी जावास्क्रिप्ट का उपयोग करने के लिए अधिक से अधिक हद तक नहीं देखता। क्या यह एक अच्छा अभ्यास नहीं है या सिर्फ हमें उन्हें जावास्क्रिप्ट में ज़रूरत नहीं है?


2
While in java or *any other language* it is mandatory to have error handling...- ज़रुरी नहीं। जावा, हाँ, लेकिन ऐसी बहुत सी भाषाएं हैं जो ट्राइ-कैच (जैसे C #) पर जोर नहीं देती हैं।
जिम जी

यह इसलिए है क्योंकि आप उन्हें एक async वातावरण में उपयोग नहीं कर सकते। मैं उन्हें अक्सर कम अमूर्त स्तर द्वारा सिंक कोड द्वारा उपयोग करता हूं, उदाहरण के लिए किसी चीज़ को किसी चीज़ में बदलकर, आदि ...
inf3rno

मैं शर्त लगाता हूं कि आप क्लाइंट-साइड कोड की तुलना में सर्वर-साइड कोड में अधिक कोशिश-कैच देखेंगे। अधिकांश क्लिप-साइड कोड जो आप प्रिवी हैं, महत्व का कुछ नहीं कर रहे हैं। मैं सबसे कम अनुप्रयोगों और ब्राउज़र साइड परिस्थितियों में - केबी को पाइप से कम करने के लिए हर त्रुटि से उबरने से अधिक महत्वपूर्ण होगा।
svidgen

हो सकता है कि एक और तरीका है कि शायद और (मोनड्स) का उपयोग करके पकड़ने की कोशिश करें, हमारे पास नोड में लिखा गया एक वेब स्क्रैपर है। हम सभी का उपयोग कर पकड़ने की कोशिश को दूर करने में सक्षम थे।
user93

जवाबों:


66

throwअनुप्रयोगों में त्रुटि की स्थितियों को पास करने के तरीके के रूप में त्रुटियों से बचना चाहिए ।

throwबयान ही प्रयोग किया जाता जाना चाहिए "ऐसा कभी नहीं करना चाहिए के लिए, दुर्घटना और जला। किसी भी तरह से सुंदर ढंग से ठीक हो न करें"

try catch हालाँकि ऐसी स्थिति में उपयोग किया जाता है जहाँ होस्ट ऑब्जेक्ट्स या ECMAScript त्रुटियां फेंक सकते हैं।

उदाहरण:

var json
try {
    json = JSON.parse(input)
} catch (e) {
    // invalid json input, set to null
    json = null
}

नोड.जेएस समुदाय में सिफारिशें हैं कि आप कॉलबैक में त्रुटियों को पास करते हैं (क्योंकि त्रुटियां केवल अतुल्यकालिक संचालन के लिए होती हैं) पहले तर्क के रूप में

fs.readFile(uri, function (err, fileData) {
    if (err) {
        // handle
        // A. give the error to someone else
        return callback(err)
        // B. recover logic
        return recoverElegantly(err)
        // C. Crash and burn
        throw err
    }
    // success case, handle nicely
})

अन्य मुद्दे भी हैं जैसे कि ट्राइ / कैच वास्तव में महंगा है और यह बदसूरत है और यह बस अतुल्यकालिक संचालन के साथ काम नहीं करता है।

इसलिए चूंकि सिंक्रोनस ऑपरेशंस में एरर नहीं आना चाहिए और यह एसिंक्रोनस ऑपरेशंस के साथ काम नहीं करता है, होस्ट ऑब्जेक्ट्स या ECMAScript द्वारा फेंकी गई एरर को छोड़कर कोई भी व्यक्ति ट्राई कैच का इस्तेमाल नहीं करता है।


2
मैं अब तक यह नहीं कहूंगा कि कोई भी कैच ट्राई नहीं करता है, यह ज्यादातर मामलों में काम के लिए गलत उपकरण है। जब वास्तव में असाधारण परिस्थितियां होती हैं, तो ए को फेंकना सार्थक हो सकता है Error, लेकिन वे कम और बहुत दूर हैं।
zzzzBov

7
@zzzzBov केस C, क्रैश और बर्न के लिए त्रुटियों को फेंकने में कुछ भी गलत नहीं है। मुझे नहीं लगता कि आपको त्रुटियों को पकड़ना चाहिए और पुनर्प्राप्त करना चाहिए। उदाहरण के लिए, document.getElementByIdजब तत्व मौजूद नहीं होता है, तो वह फेंकता नहीं है, यह सिर्फ लौटता है null। लगभग सभी मामलों के लिए एक ही किया जा सकता है
रेयनोस

4
@ रेयानोस, सिंक फ़ंक्शन से फेंकना पूरी तरह से स्वीकार्य है और उस उपयोग के मामले में समझ में आता है। कॉलबैक में त्रुटि लौटना Async के लिए है क्योंकि थ्रोइंग एरर सिंक करना है।
20art पर sbartell

@Raynos क्लाइंट-साइड (गैर-एनवायरनमेंट पर्यावरण) पर प्रवाह नियंत्रण के लिए त्रुटियों / अपवादों का उपयोग करने से बचने के लिए कोई अच्छी सलाह है? मैंने इस पोस्ट को StackOverflow पर पाया है , लेकिन यह ज्यादातर Java
blong

@ b.long सरल। त्रुटियों को कभी मत फेंको। समस्या सुलझ गयी।
रेयनोस

32

जावास्क्रिप्ट की कोशिश / पकड़ अन्य भाषाओं की तरह बुलेट-प्रूफ नहीं है, यह जावास्क्रिप्ट के अतुल्यकालिक स्वभाव के कारण है। इस स्निपेट पर विचार करें:

try {
    setTimeout(function() {
        do_something_that_throws();
    }, 1000);
}
catch (e) {
    alert("You won't see this!");
}

समस्या यह है कि नियंत्रण प्रवाह निष्पादित tryहोने से पहले ब्लॉक को छोड़ देता है do_something_that_throws(), इसलिए कॉलबैक के अंदर डाली गई त्रुटि कभी भी पकड़ में नहीं आती है।

इसलिए कई मामलों में कोशिश / पकड़ मूल रूप से अनुचित है, और यह हमेशा स्पष्ट नहीं होता है कि कुछ कोड को अतुल्यकालिक रूप से निष्पादित करता है या नहीं। सौभाग्य से, इसकी अजीब एकल-थ्रेडेड-एसिंक्रोनस-कॉलबैक मुहावरे के साथ जावास्क्रिप्ट और वास्तविक क्लोजर के लिए इसका समर्थन एक सुरुचिपूर्ण विकल्प प्रदान करता है: निरंतरता-शैली की त्रुटि से निपटने। फ़ंक्शन के रूप में किसी भी त्रुटि के लिए उचित प्रतिक्रिया दें, जैसे:

setTimeout(function () {
    do_something_that_calls_err(function(err) {
        alert("Something went wrong, namely this: " + err);
    }),
    1000);

5
यह अन्य भाषाओं में भी बुलेट प्रूफ नहीं है। उस कोड को किसी भी भाषा में पोर्ट करें जो अतुल्यकालिक कॉलबैक का समर्थन करता है और यह विफल भी हो जाएगा।
रेयनोस

2
@ रेयानोस: आप सही कह रहे हैं; हालाँकि, अन्य भाषाएँ (या बल्कि, उनकी सहायक संस्कृतियाँ) इसे अतुल्यकालिक-कॉलबैक मुहावरे में नहीं खरीदती हैं जैसा कि जावास्क्रिप्ट करता है, और अधिकांश अन्य वातावरणों की बहु-थ्रेडेड प्रकृति के कारण, कोशिश या पकड़ की कमियाँ अधिक स्पष्ट होती हैं और अन्य बहुत से घेरों से घिरा हुआ है, इसलिए लोग स्वाभाविक रूप से बहु-थ्रेडेड / अतुल्यकालिक कॉलबैक स्थितियों में सावधानी से चलते हैं, और संभावित नुकसान के बारे में अधिक जानते हैं।
tdammers

क्या यह वास्तव में जावास्क्रिप्ट के "अतुल्यकालिक प्रकृति" के कारण है? जहां तक ​​मैं देख सकता हूं, सैद्धांतिक रूप से काम करने के लिए ट्राई / कैच सैद्धांतिक रूप से बनाया जा सकता है, जैसे कि कैसे पहचानने वाले लेक्सिक रूप से बंद होते हैं; यह सिर्फ जावास्क्रिप्ट में काम करने के लिए नहीं होता है।
ब्रायन गॉर्डन

2
नोड.जेएस में = = 0.8 यह ध्यान देने योग्य है कि अतुल्यकालिक रूप से कोशिश करना / पकड़ना संभव है, कृपया मेरे प्रश्न को देखें stackoverflow.com/questions/14301839/…
बेंजामिन ग्रुएनबाउम

क्या सिंक्रोनस ट्राइ-कैच का एकमात्र विकल्प अतुल्यकालिक निरंतरता गुजर शैली है?
CMCDragonkai

23

इनमें से बहुत से उत्तर थोड़े पुराने हैं और नई ईएस 7 विशेषताओं asyncऔर को ध्यान में नहीं रखते हैं await

का उपयोग कर async/ awaitआप अब अतुल्यकालिक नियंत्रण प्रवाह प्राप्त कर सकते हैं जैसे आप चाहते हैं:

async function email(address) {
  try {
    // Do something asynchronous that may throw...
    await sendEmail({ to: address, from: 'noreply@domain.com`, subject: 'Hello' })
  } catch(err) {
    if (err instanceof SomeCustomError) {
      elegantlyHandleError(err)
    } else {
      throw err
    } 
  }
})

async/ awaitयहाँ के बारे में और जानें । आप उपयोग कर सकते हैं async/ awaitअब babel का उपयोग कर सकते हैं ।


लेकिन यह एक तुल्यकालिक कोड के समान है
अतुल अग्रवाल

@AtulAgrawal हाँ, यह बात है। Async / wait आपको सिंक्रोनस शैली में async कोड लिखने की अनुमति देता है ताकि आप "कॉलबैक नरक" और बहुत सारे वादों का एक साथ सामना करने से बच सकें। यह मेरी राय में Async कोड लिखने के लिए एक बहुत ही सुखद तरीका है
दाना वुडमैन

तो अगर हम सिंक्रोनस के लिए एसिंक्स कोड बना रहे हैं तो जावास्क्रिप्ट का उपयोग करने का क्या लाभ है। क्योंकि अधिकांश लोग अपने अतुल्य स्वभाव के कारण जावास्क्रिप्ट का उपयोग करते हैं
अतुल अग्रवाल

2
@AtulAgrawal आपको दोनों दुनियाओं में सबसे अच्छा मिलता है - आप भाषा के async प्रकृति का आनंद लेते हैं (जैसा कि ऊपर दिए गए कोड अभी भी async निष्पादित किया जाएगा - थ्रेड और सभी को मुक्त करना) और एक अधिक प्रोग्रामर-अनुकूल स्टाइलिंग के लाभों को चीरना। यह मुद्दों के बिना नहीं है, हालांकि ...
ZenMaster

15

जावास्क्रिप्ट में ट्राई-कैच किसी भी अन्य भाषा की तरह ही मान्य और उपयोगी है जो उन्हें लागू करता है। इसका एक बड़ा कारण है कि इसका अन्य भाषाओं की तरह जावास्क्रिप्ट में उपयोग नहीं किया जाता है। इसका एक ही कारण जावास्क्रिप्ट को एक बदसूरत स्क्रिप्टिंग भाषा के रूप में देखा जाता है, इसका एक ही कारण है कि लोगों को लगता है कि जावास्क्रिप्ट प्रोग्रामर असली प्रोग्रामर नहीं हैं:

  • जावास्क्रिप्ट एक अविश्वसनीय रूप से सुलभ और व्यापक भाषा है

इस तथ्य को कि इतने सारे लोग जावास्क्रिप्ट (केवल ब्राउज़रों द्वारा समर्थित भाषा के आधार पर) के संपर्क में हैं, इसका मतलब है कि आपके पास बहुत सारे अव्यवसायिक कोड हैं। बेशक कई मामूली कारण भी हैं:

  • जावास्क्रिप्ट में कुछ चीजें अतुल्यकालिक हैं और इस प्रकार catchसक्षम नहीं हैं (अतुल्यकालिक सामान)
  • इस बात को लेकर बहुत अधिक चर्चा हो गई है कि कैसे ट्रायल-कैच में भारी प्रदर्शन हुआ है। इसमें थोड़ा सा प्रदर्शन हिट है , लेकिन अधिकांश कोड के लिए, यह अच्छी तरह से लायक है।
  • जावास्क्रिप्ट (दुर्भाग्य से) एक तरह से लागू किया गया था जो अक्सर चुपचाप त्रुटियों को अनदेखा करता है (स्वचालित रूप से उदाहरण के लिए संख्याओं में परिवर्तन)

भले ही, कोशिश-कैच का उपयोग किया जाना चाहिए, लेकिन निश्चित रूप से आपको सीखना चाहिए कि उन्हें कैसे ठीक से उपयोग करना है - जैसे कि प्रोग्रामिंग में सब कुछ।


3
और तुमने कभी नीचे क्यों किया, ओह चुप डाउनवॉटर?
user250878

माना। मुझे लगता है कि स्वीकृत उत्तर आम तौर पर सच है, लेकिन देशी वस्तुओं के साथ व्यवहार करने के अलावा अन्य प्रयास, कैच और यहां तक ​​कि फेंकने का उपयोग करने के अच्छे कारण हैं। जब कॉलबैक में पास होने के बजाए कोई त्रुटि होती है, तो यह आगे के निष्पादन को रोक देता है और स्टैक को पहले ब्लॉक की तुलना में ऊपर उठाता है ताकि इसे संभाल सकें। यह एक महान लाभ है और तुल्यकालिक संचालन के लिए एकदम सही समझ में आता है, खासकर अगर वे गहरी घोंसले के शिकार होते हैं। यह अपवाद का सुझाव देने के लिए पागल लगता है "खराब" (अच्छी तरह से, स्पष्ट कारणों के अलावा) - वे वास्तव में एक अद्वितीय "शक्ति" के साथ एक बहुत ही उपयोगी उपकरण हैं।
अर्धविराम

2
क्या आपने कभी, jQuery के स्रोत कोड को पढ़ने के लिए कहा? स्वीकार किए गए उत्तर में उन परिदृश्यों का उल्लेख करने के लिए शायद ही कोई भी प्रयास हो। ऐसे कोड को कॉल करने के लिए जो ट्राइ-कैच का उपयोग नहीं करता है (जैसे jQuery) 'अनप्रोफेशनल' मूर्खतापूर्ण लगता है। सच कहूं तो, मुझे लगता है कि यह विशेष रूप से जावा से आने वाले नए जावास्क्रिप्ट प्रोग्रामर हैं जो ट्राइ-कैच जैसी भाषा सुविधाओं का उपयोग करते हैं।
स्टिजेन डे विट

6

मेरा मानना ​​है कि try..catchजावास्क्रिप्ट में बहुत कम कारण है क्योंकि भाषा में त्रुटि के लिए बहुत अधिक सहनशीलता है। अधिकांश स्थितियों को कोड की जाँच, अच्छी चूक और अतुल्यकालिक घटनाओं का उपयोग करके नियंत्रित किया जा सकता है। कुछ मामलों में, बस एक पैटर्न का उपयोग करने से मुद्दों को रोका जा सकता है:

function Foo() {
    //this may or may not be called as a constructor!!
    //could accidentally overwrite properties on window
}

function Bar() {
    if (!(this instanceof Bar)) {
        return new Bar();
    }
    //this will only work on Bar objects, and wont impact window
}

अन्य भाषाओं में कुछ प्रमुख मुद्दे जिनके कारण अपवाद उत्पन्न होते हैं, जेएस में मौजूद नहीं होते हैं। टाइप कास्टिंग को उस समय के विशाल बहुमत की आवश्यकता नहीं होती है। इसके बजाय, पसंदीदा तरीका आम तौर पर चेक (विशेष इंटरफ़ेस लागू करना) है:

function doFoo(arg) {
    if (arg.foo) {
        arg.foo();
    } else {
        Bar.prototype.foo.call(arg);
    }
}

भाषा के साथ async/ के अतिरिक्त await, try..catchअधिक प्रचलित हो रहा है। के अतुल्यकालिक रूप होने का वादा try..catchकरता है, यह समझ में आता है कि किसी को उम्मीद करनी चाहिए:

doSomething().then(
  doSomethingWithResult,
  doSomethingWithError
)

इसके बजाय के रूप में लिखा जाना चाहिए:

try {
  const result = await doSomething()
  doSomethingWithResult(result)
} catch (e) {
  doSomethingWithError(e)
}

3

संभवतः किसी अन्य कारण से कोशिश / पकड़ का उपयोग जावास्क्रिप्ट में बहुत अधिक नहीं किया जाता है, निर्माण जावास्क्रिप्ट के पहले संस्करणों में उपलब्ध नहीं था ... इसे बाद में जोड़ा गया था।

परिणामस्वरूप, कुछ पुराने ब्राउज़र इसका समर्थन नहीं करते हैं। (वास्तव में, यह कुछ पुराने ब्राउज़रों में एक पार्सर / वाक्यविन्यास त्रुटि का कारण हो सकता है, कुछ ऐसा जो अन्य प्रकार की त्रुटियों की तुलना में "रक्षात्मक रूप से प्रोग्राम करना" अधिक कठिन है।)

इससे भी महत्वपूर्ण बात यह है कि शुरू में उपलब्ध नहीं होने के बाद, जावास्क्रिप्ट बिल्डिन फ़ंक्शंस जो शुरू में जारी किए गए थे (जो कई भाषाओं में "लाइब्रेरी" फ़ंक्शन कहते हैं) इसका उपयोग नहीं करते हैं। (यह someobject.somefunction () से एक त्रुटि को "पकड़ने" के लिए बहुत अच्छी तरह से काम नहीं करता है (यदि यह "फेंक" नहीं करता है, लेकिन इसके बजाय यह "नल" लौटाता है जब यह एक समस्या का सामना करता है।)


फिर भी एक और संभावित कारण है कोशिश / पकड़ तंत्र शुरू में आवश्यक नहीं लगता था (और अभी भी यह सब उपयोगी नहीं लगता है)। यह वास्तव में केवल तभी आवश्यक होता है जब कॉल नियमित रूप से कई स्तरों पर नेस्टेड हों; बस किसी प्रकार की ERRNO लौटाना प्रत्यक्ष कॉल के लिए ठीक काम करेगा (हालाँकि जब भी यह वास्तव में उपयोगी हो, जब भी उपलब्ध हो, ज्यादातर भाषाओं में सबसे अच्छा अभ्यास यह है कि इसे हर जगह इस्तेमाल किया जाए , केवल गहरी नेस्टेड कॉल पर)। के रूप में जावास्क्रिप्ट तर्क मूल रूप से छोटे और सरल होने की उम्मीद थी (सब के बाद, यह सिर्फ एक वेबपेज :-) के लिए एक सहायक है, फ़ंक्शन कॉल गहराई से नेस्टेड होने की उम्मीद नहीं थी, और इसलिए एक कोशिश / पकड़ तंत्र आवश्यक नहीं लगता था।


3
नहीं नहीं नहीं, बिल्कुल नहीं। इंजन पुराने किसी भी लंबे समय के लिए कोई फर्क नहीं पड़ता है और सामान्य रूप से जावास्क्रिप्ट समुदाय के लिए पुराने चीजों को छोड़ने के लिए जल्दी है जब उचित है। मैं यह भी शर्त लगा सकता हूं कि जावास्क्रिप्ट डेवलपर्स के अधिकांश अब IE6 के बाद के हैं।
कैमिलो मार्टिन

0

मेरा मानना ​​है कि इनका उपयोग इसलिए नहीं किया जाता है क्योंकि जावास्क्रिप्ट क्लाइंट साइड कोड में अपवादों को फेंकना एक पृष्ठ को डीबग करना अधिक कठिन बनाता है।

अपवादों को फेंकने के बजाय, मैं आमतौर पर अल अलर्ट बॉक्स दिखाना पसंद करता हूं (यानी alert("Error, invalid...");)

यह अजीब लग सकता है, लेकिन ग्राहक की ओर से जावास्क्रिप्ट त्रुटियां होती हैं, यदि कोई ग्राहक आपके द्वारा बनाए गए पृष्ठ का उपयोग कर रहा है और पृष्ठ एक अपवाद फेंकता है, जब तक कि ग्राहक एक तकनीक-प्रेमी-कोडर नहीं है , तब तक कोई रास्ता नहीं है जो वह कभी भी बता पाएगा आप मुद्दा क्या है।

वह केवल यह कहते हुए आपको कॉल करेगा: "अरे, पेज एक्स काम नहीं करता है!", और फिर यह सब आपके लिए होगा कि यह क्या गलत है और कोड में कहां है।

इसके बजाय चेतावनी बॉक्स का उपयोग करने से यह अधिक संभावना है कि वह कॉल करता है और कुछ कहता है: "अरे, जब मैं पृष्ठ X के बटन A पर क्लिक करता हूं तो यह एक बॉक्स दिखाता है जो कहता है ..." , मुझ पर विश्वास करें, यह खोजना बहुत आसान होगा बग।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.