जावास्क्रिप्ट अपवाद हैंडलिंग


82

जावास्क्रिप्ट के भीतर फेंके गए सभी अपवादों को पकड़ने के लिए सबसे अच्छी तकनीक क्या है?

जाहिर है, सबसे अच्छी तकनीक का उपयोग करने की कोशिश है ... पकड़। लेकिन ansynchronous callbacks के साथ और इसके बाद, यह मुश्किल हो सकता है।

मुझे पता है कि IE और गेको ब्राउजर window.onerror का समर्थन करते हैं, लेकिन ओपेरा और सफारी के बारे में क्या?

यहाँ परीक्षण-मामलों का एक गुच्छा दिया गया है, जिनके लिए मैं एक केंद्रीय अपवाद हैंडलिंग समाधान रखना चाहूंगा:

// ErrorHandler-Test1
var test = null;
test.arg = 5;
// ErrorHandler-Test2
throw (new Error("Hello"));
// ErrorHandler-Test3
throw "Hello again";
// ErrorHandler-Test4
throw {
    myMessage: "stuff",
    customProperty: 5,
    anArray: [1, 2, 3]
};
// ErrorHandler-Test5
try {
    var test2 = null;
    test2.arg = 5;
} catch(e) {
    ErrorHandler.handleError(e);
}
// ErrorHandler-Test6
try {
    throw (new Error("Goodbye"));
} catch(e) {
    ErrorHandler.handleError(e);
}
// ErrorHandler-Test7
try {
    throw "Goodbye again";
} catch(e) {
    ErrorHandler.handleError(e);
}
// ErrorHandler-Test8
try {
    throw {
        myMessage: "stuff",
        customProperty: 5,
        anArray: [1, 2, 3]
    };
} catch(e) {
    ErrorHandler.handleError(e);
}

यदि आप किसी अन्य परीक्षण-मामलों के बारे में सोचते हैं, तो कृपया उनका उल्लेख करें। इनमें से कई मामलों में एक ErrorHandler.handleError विधि का उल्लेख है। यह केवल एक सुझाई गई दिशानिर्देश है जब कोशिश ... कैच का उपयोग करें।


सिर्फ इसलिए कि यह स्पष्ट है कि आपने मेरे उत्तर पर टिप्पणियों को नोटिस नहीं किया था: ऐसा लगता है कि आपने मुझे "प्रश्न में कहा गया" के लिए नीचा दिखाया, जब वह एक प्रश्न के रूप में पढ़ता है: "लेकिन ओपेरा और सफारी के बारे में क्या?" मैंने विशेष रूप से यहां एक प्रश्न का उत्तर दिया। WTF?
पलकविहीनता

1
WebKit में, 2003window.onerror से लापता एक समस्या रही है , लेकिन ऐसा लगता है कि यह अंततः हल हो रहा है । बेशक, ओपेरा अडिग रहेगा।
josh3736

FYI करें window.onerror ठीक काम करता है - Firefox 7.0.1 - IE 8 - क्रोम 16 - ओपेरा 11.60
विटाली कपलिच

11
यकीन नहीं होता कि यह क्यों बंद हो गया। दोबारा खोलने की वोटिंग हुई।
ripper234

1
सहमत, यह एक उपयोगी प्रश्न है। केवल एक चीज जिसके बारे में मैं सोच सकता हूं कि कास्परऑन को डर है कि यह बदले में किसी प्रकार की ब्राउज़र वॉर चर्चा बन जाएगी?
जॉर्डन रीटर

जवाबों:


23

यदि आप अपने सभी ईवेंट हैंडलर्स को असाइन करने के लिए jQuery जैसी लाइब्रेरी का उपयोग करते हैं, तो आप window.onerrorjQuery ईवेंट हैंडलर कोड के संयोजन और रैपिंग हैंडल फ़ंक्शन के साथ तैयार फ़ंक्शन का उपयोग कर सकते हैं (देखें: जावास्क्रिप्ट एरर ट्रैकिंग: Why window.onerror पर्याप्त नहीं है )।

  • window.onerror: IE (और फ़ायरफ़ॉक्स में सबसे त्रुटियों) में सभी त्रुटियों को पकड़ता है, लेकिन सफारी और ओपेरा में कुछ भी नहीं करता है।
  • jQuery ईवेंट हैंडलर: सभी ब्राउज़रों में jQuery ईवेंट त्रुटियों को पकड़ता है।
  • jQuery के तैयार कार्य: सभी ब्राउज़रों में आरंभिक त्रुटियों को पकड़ता है।

मैंने पहले ही लेख पढ़ा था जो किसी भी समाधान की पेशकश नहीं करता है। मैं jQuery का उपयोग नहीं करता, लेकिन मैं इस बात से चिंतित हूं कि आप क्या कर रहे हैं। क्या आप कह रहे हैं कि jQuery अपवाद खा रहा है ?! या क्या वे केवल एक लॉगिंग कार्यक्षमता प्रदान करते हैं (जो कि मेरे मूल प्रश्न का उत्तर दिए जाने के बाद ही उपयोगी है)?
harley.333

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

2
प्रदान किया गया लिंक स्थानांतरित हो गया: blogs.cozi.com/tech/2008/04/…
natacado

1
क्या यह अभी भी सच है? मैंने सिर्फ onerrorसफारी + क्रोम पर सामान्य हैंडलिंग दृष्टिकोण की कोशिश की और ठीक से काम करने लगता है।
जुरी

आपने जो लिंक "यह पर्याप्त नहीं है" दिया है वह बहुत पुरानी जानकारी है और अब ऐसा नहीं है।
vsync

21

WebKit (Safari, Chrome, आदि) अब समर्थन करता प्रतीत होता है onerror

मूल पोस्ट: जहां तक ​​मुझे पता है, WebKit / Safari onerrorघटना का समर्थन नहीं करता है । जो धिक्कार है।


19
उह, नहीं यह नहीं है। सवाल में पूछा: "लेकिन ओपेरा और सफारी के बारे में क्या?"
पलकविहीनता

जैसा कि, मैंने विशेष रूप से प्रश्नोत्तर में प्रस्तुत एक प्रश्न का उत्तर दिया।
पलकविहीनता

8
मुझे लगता है कि वह ओपेरा और सफारी के बारे में "मैं क्या करता हूं" का मतलब है [जिसके पास विंडो नहीं है ।errerror]? "
निकफ

10
@nickf, हो सकता है, लेकिन यदि ऐसा है तो यह बहुत बुरी तरह से शब्दबद्ध है, और मेरी व्याख्या सबसे खराब और कम से कम सबसे अधिक संभावना है। यह लोगों को मेरा उत्तर नीचे वोट करने के लिए के लिए एक सुंदर गरीब कारण है विशेष रूप से यह देखते हुए कि सवाल यह नहीं है राज्य यह, और अन्य पाठकों का सकारात्मक या नकारात्मक बयान से लाभ हो सकता।
पलकहीनता

क्रोम अब इसका समर्थन करता है।
डैनियल एक्स मूर

7

दरअसल, jquery का तरीका इतना बुरा नहीं है। देख:

http://docs.jquery.com/Events/error#fn

तथा:

$(window).error(function(msg, url, line){
  $.post("js_error_log.php", { msg: msg, url: url, line: line });
});

11
अब इसे खोजने वाले किसी के लिए भी - jquery वास्तव में किसी ईवेंट को window.error इवेंट के लिए बाध्य नहीं करने की अनुशंसा करता है - ऊपर दिए गए दस्तावेज़ लिंक देखें। निकालें: एक jQuery त्रुटि ईवेंट हैंडलर को विंडो ऑब्जेक्ट से संलग्न नहीं किया जाना चाहिए। [...] इसके बजाय window.onerror का उपयोग करें।
zcrar70

toc यह इस तरह से बाँधने वाला नहीं है, यह अतार्किक है! कई गलतियां तब तक हो सकती हैं जब तक यह बाइंडिंग बना दिया गया था (यदि इसे सफलतापूर्वक भी बनाया गया था ...)
vsync

6

अपने स्वयं के अपवाद हैंडलर के साथ सभी अपवादों को पकड़ें और इंस्टोफ का उपयोग करें।

$("inuput").live({
    click : function (event) {
        try {
            if (somethingGoesWrong) {
                throw new MyException();
            }
        } catch (Exception) {
            new MyExceptionHandler(Exception);
        }

    }
});

function MyExceptionHandler(Exception) {
    if (Exception instanceof TypeError || 
        Exception instanceof ReferenceError || 
        Exception instanceof RangeError ||  
        Exception instanceof SyntaxError ||     
        Exception instanceof URIError ) {
        throw Exception; // native error
     } else {
         // handle exception
     }
}

MyExcetpionHandler मूल त्रुटि को फेंक देगा क्योंकि कोई भी प्रयास नहीं है - ब्लॉक।

यात्रा http://www.nczonline.net/blog/2009/03/10/the-art-of-throwing-javascript-errors-part-2/


4

try-catchहमेशा सबसे अच्छा समाधान नहीं है। उदाहरण के लिए, Chrome 7.0 में आप कंसोल विंडो में अच्छा स्टैक ट्रेस खो देते हैं। अपवाद को रोकना मदद नहीं करता है। मुझे ऐसे किसी समाधान का पता नहीं है जो स्टैक के निशान को संरक्षित करता है और आपको अपवाद पर प्रतिक्रिया देता है।


2

थोड़े से काम से स्टैकट्रैक्स प्राप्त करना संभव है जो सभी ब्राउज़रों में यथोचित रूप से पूरा हो गया है।

आधुनिक क्रोम और ओपेरा (यानी ब्लिंक रेंडरिंग इंजन के आसपास कुछ भी) पूरी तरह से ErrorEvent और के लिए HTML 5 ड्राफ्ट युक्ति का समर्थन करते हैं window.onerror। इन दोनों ब्राउज़रों में आप या तो window.onerror(या आश्चर्यजनक रूप से!) 'त्रुटि' घटना को ठीक से बाँध सकते हैं:

// Only Chrome & Opera pass the error object.
window.onerror = function (message, file, line, col, error) {
    console.log(message, "from", error.stack);
    // You can send data to your server
    // sendData(data);
};
// Only Chrome & Opera have an error attribute on the event.
window.addEventListener("error", function (e) {
    console.log(e.error.message, "from", e.error.stack);
    // You can send data to your server
    // sendData(data);
})

दुर्भाग्य से फ़ायरफ़ॉक्स, सफारी और IE अभी भी आसपास हैं और हमें उनका भी समर्थन करना होगा। जैसा कि स्टैकट्रेस उपलब्ध नहीं है, window.onerrorहमें थोड़ा और काम करना होगा।

यह पता चला है कि त्रुटियों से स्टैकट्रैक प्राप्त करने के लिए हम केवल एक चीज को अपने सभी कोड को एक try{ }catch(e){ }ब्लॉक में लपेट सकते हैं और फिर ई.स्टैक को देख सकते हैं। हम एक फ़ंक्शन के साथ प्रक्रिया को कुछ आसान बना सकते हैं जिसे रैप कहा जाता है जो एक फ़ंक्शन लेता है और अच्छी त्रुटि हैंडलिंग के साथ एक नया फ़ंक्शन देता है।

function wrap(func) {
    // Ensure we only wrap the function once.
    if (!func._wrapped) {
        func._wrapped = function () {
            try{
                func.apply(this, arguments);
            } catch(e) {
                console.log(e.message, "from", e.stack);
                // You can send data to your server
                // sendData(data);
                throw e;
            }
        }
    }
    return func._wrapped;
};

यह काम। कोई भी फ़ंक्शन जिसे आप मैन्युअल रूप से लपेटते हैं, अच्छी त्रुटि हैंडलिंग होगी।

आप निम्नानुसार छवि टैग का उपयोग करके डेटा भेज सकते हैं

function sendData(data) {
    var img = newImage(),
        src = http://yourserver.com/jserror + '&data=' + encodeURIComponent(JSON.stringify(data));

    img.crossOrigin = 'anonymous';
    img.onload = function success() {
        console.log('success', data);
    };
    img.onerror = img.onabort = function failure() {
        console.error('failure', data);
    };
    img.src = src;
}

हालाँकि आपको डेटा एकत्र करने के लिए बैकएंड करना होगा और डेटा की कल्पना करने के लिए फ्रंट-एंड करना होगा।

पर Atatus , हम इस समस्या को हल करने पर काम कर रहे हैं। त्रुटि ट्रैकिंग से अधिक, Atatus वास्तविक उपयोगकर्ता निगरानी प्रदान करता है।

एक कोशिश दे दो https://www.atatus.com/

अस्वीकरण: मैं Atatus में एक वेब डेवलपर हूं।


1

यह सच है कि आधुनिक ब्राउज़रों के साथ, त्रुटियों के लिए window.onerror हुकिंग करना जो सभी तरह से शीर्ष पर बुलबुला बनाता है साथ ही अजाक्स त्रुटियों के लिए jQuery इवेंट हैंडलर जोड़ने से व्यावहारिक रूप से आपके क्लाइंट कोड में डाली गई सभी त्रुटि ऑब्जेक्ट पकड़ लेंगे। यदि आप मैन्युअल रूप से window.onerror के लिए एक हैंडलर स्थापित कर रहे हैं, तो आधुनिक ब्राउज़रों में यह किया जाता है window.addEventListener('error', callback), जबकि IE8 / 9 में आपको कॉल करने की आवश्यकता होती है window.attachEvent('onerror', callback)

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

मुख्य मुद्दा यह डेटा उत्पादन में प्रदान कर रहा है, क्योंकि आपके उपयोगकर्ता ब्राउज़रों और संस्करणों की एक व्यापक श्रेणी को चलाने की गारंटी देते हैं, जिससे आप संभवतः परीक्षण कर सकते हैं, और आपकी साइट / ऐप अप्रत्याशित तरीके से टूट जाएंगे, चाहे आप कितने भी क्यूए पर फेंक दें। यह।

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

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

Raygun4js क्लाइंट लाइब्रेरी भी साथ आता है window.onerrorके रूप में jQuery आउट-ऑफ-द-बॉक्स हुक, दोनों आधुनिक और विरासत ब्राउज़रों के लिए और साथ ही, इसलिए इस सेट करने के लिए आप केवल जोड़ने की जरूरत है:

<script type="text/javascript" src="//cdn.raygun.io/raygun4js/raygun.min.js" </script> <script> Raygun.init('yourApiKey').attach(); </script>

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

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


0

मैं भी त्रुटि से निपटने और स्टैकट्रेस की तलाश कर रहा था और उपयोगकर्ता कार्यों के लिए लॉग इन कर रहा था यही मुझे आशा है कि यह आपको https://github.com/jefferyto/glitchjs भी मदद करता है

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