2015-10-29 5 views
32

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

process.on('unhandledRejection', function(reason, p) { 
    console.log("Unhandled Rejection:", reason.stack); 
    process.exit(1); 
}); 

यह डिबगिंग उद्देश्यों के लिए ठीक काम करता है।

उत्पादन में हालांकि मैं 500 त्रुटि वाले हैंडलर को ट्रिगर करना चाहता हूं, ताकि उपयोगकर्ता को "कुछ गलत हो गया" पृष्ठ दिखाया जा सके।

app.use(function(error, req, res, next) { 
    res.status(500); 
    res.render('500'); 
}); 

एक मध्यस्थ के अंदर unhandledRejection लाना के रूप में यह async है और offen परिणाम एक Error: Can't render headers after they are sent to the client.

में मैं कैसे प्रतिपादन के बारे में जाना होगा काम नहीं करता है: मैं इस पकड़ सभी त्रुटि हैंडलर है कि वर्तमान में अन्य अपवाद के लिए काम करता है unhandledRejection पर 500 पेज?

उत्तर

15

एक मध्यस्थ के अंदर unhandledRejection लाना ... अक्सर एक Error: Can't render headers after they are sent to the client.

में मामूली बनाओ परिणाम ExpressJS Documentation से

// production error handler 
const HTTP_SERVER_ERROR = 500; 
app.use(function(err, req, res, next) { 
    if (res.headersSent) { 
    return next(err); 
    } 

    return res.status(err.status || HTTP_SERVER_ERROR).render('500'); 
}); 

: अपने त्रुटि हैंडलर के लिए बदल

एक्सप्रेस एक अंतर्निहित त्रुटि हैंडलर के साथ आता है, जो ऐप में होने वाली किसी भी त्रुटि का ख्याल रखता है। यह डिफ़ॉल्ट त्रुटि-हैंडलिंग मिडलवेयर मिडलवेयर स्टैक के अंत में जोड़ा जाता है।

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

उत्पादन मोड में ऐप चलाने के लिए पर्यावरण चर NODE_ENV को "उत्पादन" पर सेट करें।

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

तो जब आप एक कस्टम त्रुटि हैंडलर जोड़ते हैं तो आप एक्सप्रेस में डिफ़ॉल्ट त्रुटि हैंडलिंग तंत्र को प्रतिनिधि करना चाहते हैं, जब शीर्षलेख क्लाइंट को पहले ही भेज दिया गया हो।

3

यह मानते हुए कि आप एक्सप्रेस और कुछ वादा आधारित कोड की तरह तो उपयोग कर रहे हैं:

readFile() .then(readAnotherFile) .then(doSomethingElse) .then(...)

तेरा वादा श्रृंखला के अंत करने के लिए एक .catch(next) जोड़ें और एक्सप्रेस के मिडलवेयर सफलतापूर्वक दोनों तुल्यकालिक/अतुल्यकालिक कोड संभाल लेंगे आपके उत्पादन त्रुटि हैंडलर।

यहाँ एक महान लेख है कि आप के लिए क्या देख रहे करने के लिए में गहराई से चला जाता है है: https://strongloop.com/strongblog/async-error-handling-expressjs-es7-promises-generators/

13

मैं एक catch कॉलबैक (उर्फ errback) रूप next तर्क का उपयोग कर रहा है किसी भी बिना क्रिया अस्वीकृति अग्रेषित करने के लिए त्रुटि हैंडलर व्यक्त करने के लिए:

app.get('/foo', function (req, res, next) { 
    somePromise 
    .then(function (result) { 
     res.send(result); 
    }) 
    .catch(next); // <----- NOTICE! 
} 

या कम प्रपत्र:

app.get('/foo', function (req, res, next) { 
    somePromise 
    .then(function (result) { 
     res.send(result); 
    }, next); // <----- NOTICE! 
} 

और तो हम एक्सप्रेस त्रुटि हैंडलर में err तर्क के साथ सार्थक त्रुटि प्रतिक्रिया उत्सर्जित कर सकते हैं।

उदाहरण के लिए

,

app.use(function (err, req, res, /*unused*/ next) { 
    // bookshelf.js model not found error 
    if (err.name === 'CustomError' && err.message === 'EmptyResponse') { 
    return res.status(404).send('Not Found'); 
    } 
    // ... more error cases... 
    return res.status(500).send('Unknown Error'); 
}); 

IMHO, वैश्विक unhandledRejection घटना अंतिम जवाब नहीं है।

उदाहरण के लिए, इस स्मृति रिसाव की संभावना है:

app.use(function (req, res, next) { 
    process.on('unhandledRejection', function(reason, p) { 
    console.log("Unhandled Rejection:", reason.stack); 
    res.status(500).send('Unknown Error'); 
    //or next(reason); 
    }); 
}); 

लेकिन इस भी भारी है:

app.use(function (req, res, next) { 
    var l = process.once('unhandledRejection', function(reason, p) { 
    console.log("Unhandled Rejection:", reason.stack); 
    res.status(500).send('Unknown Error'); 
    //next(reason); 
    }); 
    next(); 
    process.removeEventLister('unhandledRejection', l); 
}); 

IMHO, expressjs वादा के लिए बेहतर समर्थन की जरूरत है।

+0

इसलिए हमें हमेशा त्रुटियों को संभालने के लिए 'अगली' का उपयोग करना चाहिए और वादा अस्वीकृति के लिए कोई वैश्विक त्रुटि हैंडलर नहीं है :(यह इतना बुरा है! –

2

मुझे लगता है कि express-promise-router बिल्कुल इस समस्या को हल करने के लिए बनाया गया था। यह आपके मार्गों को वादे वापस करने की अनुमति देता है, और next(err) पर कॉल करेगा यदि ऐसा वादा किसी त्रुटि के साथ खारिज कर दिया गया है।

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