Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
466 views
in Technique[技术] by (71.8m points)

node.js - Node.js最佳实践异常处理(Node.js Best Practice Exception Handling)

I just started trying out node.js a few days ago.

(几天前我才开始尝试使用node.js。)

I've realized that the Node is terminated whenever I have an unhandled exception in my program.

(我意识到只要程序中有未处理的异常,Node就会终止。)

This is different than the normal server container that I have been exposed to where only the Worker Thread dies when unhandled exceptions occur and the container would still be able to receive the request.

(这与我所接触过的普通服务器容器不同,在普通服务器容器中,当发生未处理的异常时,只有工作线程死亡,并且容器仍然能够接收请求。)

This raises a few questions:

(这引起了一些问题:)

  • Is process.on('uncaughtException') the only effective way to guard against it?

    (是process.on('uncaughtException')防范的唯一有效方法吗?)

  • Will process.on('uncaughtException') catch the unhandled exception during execution of asynchronous processes as well?

    (process.on('uncaughtException')也会在异步进程执行期间捕获未处理的异常吗?)

  • Is there a module that is already built (such as sending email or writing to a file) that I could leverage in the case of uncaught exceptions?

    (是否存在已经构建的模块(例如,发送电子邮件或写入文件),在未捕获的异常的情况下可以利用该模块?)

I would appreciate any pointer/article that would show me the common best practices for handling uncaught exceptions in node.js

(我将不胜感激任何向我展示如何处理node.js中未捕获异常的常见最佳实践的指针/文章)

  ask by momo translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Update: Joyent now has their own guide .

(更新:Joyent现在有自己的指南 。)

The following information is more of a summary:

(以下信息更多是摘要:)

Safely "throwing" errors (安全地“抛出”错误)

Ideally we'd like to avoid uncaught errors as much as possible, as such, instead of literally throwing the error, we can instead safely "throw" the error using one of the following methods depending on our code architecture:

(理想情况下,我们希望尽可能避免未捕获的错误,因此,除了从字面上抛出错误之外,我们还可以根据我们的代码体系结构使用以下方法之一安全地“抛出”错误:)

  • For synchronous code, if an error happens, return the error:

    (对于同步代码,如果发生错误,请返回错误:)

     // Define divider as a syncrhonous function var divideSync = function(x,y) { // if error condition? if ( y === 0 ) { // "throw" the error safely by returning it return new Error("Can't divide by zero") } else { // no error occured, continue on return x/y } } // Divide 4/2 var result = divideSync(4,2) // did an error occur? if ( result instanceof Error ) { // handle the error safely console.log('4/2=err', result) } else { // no error occured, continue on console.log('4/2='+result) } // Divide 4/0 result = divideSync(4,0) // did an error occur? if ( result instanceof Error ) { // handle the error safely console.log('4/0=err', result) } else { // no error occured, continue on console.log('4/0='+result) } 
  • For callback-based (ie. asynchronous) code, the first argument of the callback is err , if an error happens err is the error, if an error doesn't happen then err is null .

    (对于基于回调的(即异步)代码,回调的第一个参数为err ,如果发生err是错误,如果未发生错误则errnull 。)

    Any other arguments follow the err argument:

    (任何其他参数都遵循err参数:)

     var divide = function(x,y,next) { // if error condition? if ( y === 0 ) { // "throw" the error safely by calling the completion callback // with the first argument being the error next(new Error("Can't divide by zero")) } else { // no error occured, continue on next(null, x/y) } } divide(4,2,function(err,result){ // did an error occur? if ( err ) { // handle the error safely console.log('4/2=err', err) } else { // no error occured, continue on console.log('4/2='+result) } }) divide(4,0,function(err,result){ // did an error occur? if ( err ) { // handle the error safely console.log('4/0=err', err) } else { // no error occured, continue on console.log('4/0='+result) } }) 
  • For eventful code, where the error may happen anywhere, instead of throwing the error, fire the error event instead :

    (对于事件代码,错误可能在任何地方发生,而不是引发错误,请引发error事件 :)

     // Definite our Divider Event Emitter var events = require('events') var Divider = function(){ events.EventEmitter.call(this) } require('util').inherits(Divider, events.EventEmitter) // Add the divide function Divider.prototype.divide = function(x,y){ // if error condition? if ( y === 0 ) { // "throw" the error safely by emitting it var err = new Error("Can't divide by zero") this.emit('error', err) } else { // no error occured, continue on this.emit('divided', x, y, x/y) } // Chain return this; } // Create our divider and listen for errors var divider = new Divider() divider.on('error', function(err){ // handle the error safely console.log(err) }) divider.on('divided', function(x,y,result){ console.log(x+'/'+y+'='+result) }) // Divide divider.divide(4,2).divide(4,0) 

Safely "catching" errors (安全地“捕捉”错误)

Sometimes though, there may still be code that throws an error somewhere which can lead to an uncaught exception and a potential crash of our application if we don't catch it safely.

(但是有时,仍然有一些代码会在某个地方抛出错误,如果我们不安全地捕获它,可能会导致未捕获的异常,并可能导致应用程序崩溃。)

Depending on our code architecture we can use one of the following methods to catch it:

(根据我们的代码体系结构,我们可以使用以下方法之一来捕获它:)

  • When we know where the error is occurring, we can wrap that section in a node.js domain

    (当我们知道错误发生在哪里时,可以将该部分包装在node.js域中)

     var d = require('domain').create() d.on('error', function(err){ // handle the error safely console.log(err) }) // catch the uncaught errors in this asynchronous or synchronous code block d.run(function(){ // the asynchronous or synchronous code that we want to catch thrown errors on var err = new Error('example') throw err }) 
  • If we know where the error is occurring is synchronous code, and for whatever reason can't use domains (perhaps old version of node), we can use the try catch statement:

    (如果我们知道错误发生在哪里是同步代码,并且由于某种原因不能使用域(也许是旧版本的节点),则可以使用try catch语句:)

     // catch the uncaught errors in this synchronous code block // try catch statements only work on synchronous code try { // the synchronous code that we want to catch thrown errors on var err = new Error('example') throw err } catch (err) { // handle the error safely console.log(err) } 

    However, be careful not to use try...catch in asynchronous code, as an asynchronously thrown error will not be caught:

    (但是,请注意不要在异步代码中使用try...catch ,因为将不会捕获异步引发的错误:)

     try { setTimeout(function(){ var err = new Error('example') throw err }, 1000) } catch (err) { // Example error won't be caught here... crashing our app // hence the need for domains } 

    If you do want to work with try..catch in conjunction with asynchronous code, when running Node 7.4 or higher you can use async/await natively to write your asynchronous functions.

    (如果您确实想将try..catch与异步代码一起使用,则在运行Node 7.4或更高版本时,可以本地使用async/await编写异步函数。)

    Another thing to be careful about with try...catch is the risk of wrapping your completion callback inside the try statement like so:

    (使用try...catch要注意的另一件事是将完成回调包装在try语句中的风险,如下所示:)

     var divide = function(x,y,next) { // if error condition? if ( y === 0 ) { // "throw" the error safely by calling the completion callback // with the first argument being the error next(new Error("Can't divide by zero")) } else { // no error occured, continue on next(null, x/y) } } var continueElsewhere = function(err, result){ throw new Error('elsewhere has failed') } try { divide(4, 2, continueElsewhere) // ^ the execution of divide, and the execution of // continueElsewhere will be inside the try statement } catch (err) { console.log(err.stack) // ^ will output the "unexpected" result of: elsewhere has failed } 

    This gotcha is very easy to do as your code becomes more complex.

    (随着代码变得更加复杂,此陷阱非常容易实现。)

    As such, it is best to either use domains or to return errors to avoid (1) uncaught exceptions in asynchronous code (2) the try catch catching execution that you don't want it to.

    (因此,最好使用域或返回错误,以避免(1)异步代码中未捕获的异常(2)尝试捕获不需要的执行。)

    In languages that allow for proper threading instead of JavaScript's asynchronous event-machine style, this is less of an issue.

    (在允许适当的线程而不是JavaScript的异步事件机器风格的语言中,这不是问题。)

  • Finally, in the case where an uncaught error happens in a place that wasn't wrapped in a domain or a try catch statement, we can make our application not crash by using the uncaughtException listener (however doing so can put the application in an unknown state ):

    (最后,在未包裹域或try catch语句的地方发生未捕获的错误的情况下,我们可以使用uncaughtException侦听器使应用程序不崩溃(但是这样做会使应用程序处于未知状态)状态 ):)

     // catch the uncaught errors that weren't wrapped in a domain or try catch statement // do not use this in modules, but only in applications, as otherwise we could have multiple of these bound process.on('uncaughtException', function(err) { // handle the error safely console.log(err) }) // the asynchronous or synchronous code that emits the otherwise uncaught error var err = new Error('example') throw err 

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...