2012-04-30 18 views
22

मैं एक्सप्रेस के प्रलेखन के माध्यम से चला गया, और the part describing error handling मेरे लिए पूरी तरह से अपारदर्शी है।node.js में कोड अपवादों को कैसे संभालें?

मुझे लगा कि app वे एक उदाहरण createServer() का जिक्र कर रहे हैं, है ना? लेकिन मुझे कोई संकेत नहीं है कि अनुरोध को संभालने के दौरान अपवाद होने पर अनुप्रयोग प्रक्रिया को उड़ाने से node.js को कैसे रोकें।

मुझे वास्तव में कुछ भी कल्पना की आवश्यकता नहीं है; जब भी कोई अपवाद होता है, तो मैं बस 500 की स्थिति और अन्यथा खाली प्रतिक्रिया वापस करना चाहता हूं। नोड प्रक्रिया को समाप्त नहीं करना चाहिए क्योंकि कहीं कहीं अपरिचित अपवाद नहीं था।

क्या यह हासिल करने का एक सरल उदाहरण है?


var express = require('express'); 
var http = require('http'); 

var app = express.createServer(); 

app.get('/', function(req, res){ 
    console.log("debug", "calling") 
    var options = { 
     host: 'www.google.com', 
     port: 80, 
     path: "/" 
    }; 
    http.get(options, function(response) { 
     response.on("data", function(chunk) { 
      console.log("data: " + chunk); 
      chunk.call(); // no such method; throws here 
     }); 
    }).on('error', function(e) { 
     console.log("error connecting" + e.message); 
    }); 
}); 

app.configure(function(){ 
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 
}); 

app.listen(3000); 

पूरे अनुप्रयोग क्रैश हो, ट्रैस बैक उत्पादन

mypath/tst.js:16 
      chunk.call(); // no such method; throws here 
       ^TypeError: Object ... has no method 'call' 
    at IncomingMessage.<anonymous> (/Library/WebServer/Documents/discovery/tst.js:16:18) 
    at IncomingMessage.emit (events.js:67:17) 
    at HTTPParser.onBody (http.js:115:23) 
    at Socket.ondata (http.js:1150:24) 
    at TCP.onread (net.js:374:27) 
+0

'सिर्फ इसलिए कि वहाँ प्रक्रिया somewhere.' न आया हुआ अपवाद था *** *** मर जाएगा अगर वहाँ एक * ध्यान में न आया * अपवाद। यदि आप अपवाद होने पर इसे समाप्त नहीं करना चाहते हैं, तो अपवाद पकड़ें और 500 त्रुटि लौटाएं। – Chad

+2

आपको गैर-एक्सप्रेस तरीके से रुचि हो सकती है: http://stackoverflow.com/questions/4213351/make-node-js-not-exit-on-error – Matt

+0

उत्कृष्ट, बहुत धन्यवाद @ मैट! – user124114

उत्तर

2

आप डिफ़ॉल्ट त्रुटि हैंडलर कि का उपयोग करता है व्यक्त करते हैं, जो वास्तव में connect error handler है उपयोग कर सकते हैं।

var app = require('express').createServer(); 

app.get('/', function(req, res){ 
    throw new Error('Error thrown here!'); 
}); 

app.configure(function(){ 
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 
}); 

app.listen(3000); 

अद्यतन अपने कोड के लिए, आप वास्तव में इस

var express = require('express'); 
var http = require('http'); 

var app = express.createServer(); 

app.get('/', function (req, res, next) { 
    console.log("debug", "calling"); 
    var options = { 
    host:'www.google.com', 
    port:80, 
    path:"/" 
    }; 
    http.get(options, 
    function (response) { 
     response.on("data", function (chunk) { 
     try { 
      console.log("data: " + chunk); 
      chunk.call(); // no such method; throws here 

     } 
     catch (err) { 
      return next(err); 
     } 
     }); 
    }).on('error', function (e) { 
     console.log("error connecting" + e.message); 
    }); 
}); 

app.configure(function() { 
    app.use(express.errorHandler({ dumpExceptions:true, showStack:true })); 
}); 

app.listen(3000); 
+0

आपका उदाहरण काम करता है ('var express = requ (' express ');') जोड़ने के बाद, लेकिन दुर्भाग्यवश जब मैं अपने कोड में एक ही चीज़ करता हूं तो यह अभी भी प्रक्रिया को क्रैश करता है। मैंने नमूना कोड के साथ प्रश्न अद्यतन किया है। – user124114

+0

मैंने जवाब को अद्यतन किया है कि त्रुटि को कैप्चर करने और अगले() का उपयोग करके इसे व्यक्त करने के लिए पास किया गया है। – 250R

+0

धन्यवाद @ 250 आर! दुर्भाग्य से मैं इस तरह की संरचनाओं के साथ हर जगह कोड तर्क को कूड़ेदान पर बर्दाश्त नहीं कर सकता, इसलिए मैं ऊपर दिए गए टिप्पणियों में समाधान मैट से जुड़ा हुआ हूं। – user124114

38

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

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

अभ्यास में इसका क्या अर्थ है कि यदि आप अपवाद फेंकते हैं और इसे स्वयं नहीं पकड़ते हैं और आप ऐसा करते हैं एक्सप्रेस, एक्सप्रेस द्वारा सीधे कॉल किया गया एक समारोह छोड़कर पकड़ सकता है n और आपके द्वारा इंस्टॉल किए गए त्रुटि हैंडलर को कॉल करें, मान लें कि आपने app.use(express.errorHandler()) जैसे त्रुटि-हैंडलिंग मिडलवेयर का कुछ टुकड़ा कॉन्फ़िगर किया है। लेकिन अगर आप एक ऐसे अपवाद को फेंक देते हैं जिसे एसिंक्रोनस इवेंट के जवाब में बुलाया गया था, तो एक्सप्रेस इसे पकड़ने में सक्षम नहीं होगा। (इसे पकड़ने का एकमात्र तरीका वैश्विक नोड uncaughtException ईवेंट सुनना है, जो पहले एक बुरा विचार होगा क्योंकि यह वैश्विक है और आपको इसे अन्य चीजों के लिए उपयोग करने की आवश्यकता हो सकती है, और दूसरा क्योंकि एक्सप्रेस को पता नहीं होगा कि अनुरोध क्या था अपवाद से जुड़ा हुआ है।)

यहां एक उदाहरण है।मैं किसी मौजूदा एक्सप्रेस ऐप्लिकेशन के लिए मार्ग-हैंडलिंग कोड के इस स्निपेट जोड़ें:

app.get('/fail/sync', function(req, res) { 
    throw new Error('whoops'); 
}); 
app.get('/fail/async', function(req, res) { 
    process.nextTick(function() { 
     throw new Error('whoops'); 
    }); 
}); 

अब अगर मैं अपने ब्राउज़र में http://localhost:3000/fail/sync जाते हैं, तो ब्राउज़र एक कॉल स्टैक (कार्रवाई में express.errorHandler दिखा) उदासीनता। यदि मैं अपने ब्राउज़र में http://localhost:3000/fail/async पर जाता हूं, हालांकि, ब्राउज़र गुस्सा हो जाता है (क्रोम एक "कोई डेटा प्राप्त नहीं हुआ: त्रुटि 324, नेट :: ERR_EMPTY_RESPONSE: सर्वर ने कोई डेटा भेजने के बिना कनेक्शन बंद कर दिया" संदेश दिखाता है, क्योंकि नोड प्रक्रिया समाप्त हो गई है , टर्मिनल में stdout पर एक बैकट्रैक दिखा रहा है जहां मैंने इसे बुलाया था।

+5

यह वास्तव में एक उत्कृष्ट उत्तर है क्योंकि यह स्पष्ट रूप से स्पष्ट नहीं है कि एक्सप्रेस कैसे अपवाद को पकड़ता है और उन्हें त्रुटि मिडलवेयर (जो एक अप्रत्याशित डिफ़ॉल्ट व्यवहार है) के साथ संभालता है, लेकिन यह भी बताता है कि 'नई त्रुटि फेंकने' का उपयोग कैसे किया जाता है, ... ") 'async फ़ंक्शंस में त्रुटि मिडलवेयर ट्रिगर नहीं करेगा और वास्तव में एसिंक फ़ंक्शन को लपेटने वाले अपवाद हैंडलर द्वारा भी पकड़ा नहीं जाएगा। आप कहीं और यह जानकारी नहीं पा सकते हैं। – fthinker

+2

[डोमेन] का उपयोग करना (http://nodejs.org/api/domain.html) 'uncaughtException' को पकड़ने के लिए एक बेहतर विकल्प है। – James

+2

डोमेन बहिष्कृत होने की प्रक्रिया में हैं। वैकल्पिक एपीआई क्या है? –

10

असीमित त्रुटियों को पकड़ने में सक्षम होने के लिए मैं डोमेन का उपयोग करता हूं। एक्सप्रेस के साथ आप इस कोड की कोशिश कर सकते हैं:

function domainWrapper() { 
    return function (req, res, next) { 
     var reqDomain = domain.create(); 
     reqDomain.add(req); 
     reqDomain.add(res); 

     res.on('close', function() { 
      reqDomain.dispose(); 
     }); 
     reqDomain.on('error', function (err) { 
      next(err);    
     }); 
     reqDomain.run(next) 
    } 
} 
app.use(domainWrapper()); 
//all your other app.use 
app.use(express.errorHandler()); 

यह कोड आपके अतुल्यकालिक त्रुटि पर कब्जा कर लिया और अपने त्रुटि हैंडलर के लिए भेजा जा कर देगा। इस उदाहरण में मैं express.errorHandler का उपयोग करता हूं, लेकिन यह किसी भी हैंडलर के साथ काम करता है।

डोमेन के बारे में अधिक जानकारी के लिए: http://nodejs.org/api/domain.html

+0

यहां एक एनपीएम पैकेज है यह करें: https://www.npmjs.com/package/express-domain-middleware – pjincz

+0

सर्वोत्तम उत्तर/समाधान! – felixfbecker

+3

'डोमेन' मॉड्यूल बहिष्करण लंबित है। तो मैं इसका इस्तेमाल करने की सिफारिश नहीं करता। – mauvm

संबंधित मुद्दे