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中未捕获异常的常见最佳实践的指针/文章


#1楼

参考:https://stackoom.com/question/Ufnd/Node-js最佳实践异常处理


#2楼

I would just like to add that Step.js library helps you handle exceptions by always passing it to the next step function. 我只想补充一点, Step.js库通过始终将其传递给下一步函数来帮助您处理异常。 Therefore you can have as a last step a function that check for any errors in any of the previous steps. 因此,您可以在最后一步拥有一个功能,该功能可以检查前面任何步骤中的任何错误。 This approach can greatly simplify your error handling. 这种方法可以大大简化您的错误处理。

Below is a quote from the github page: 以下是github页面的引文:

any exceptions thrown are caught and passed as the first argument to the next function. 捕获所有抛出的异常,并将其作为第一个参数传递给下一个函数。 As long as you don't nest callback functions inline your main functions this prevents there from ever being any uncaught exceptions. 只要您不将回调函数嵌套到主函数中,就可以防止任何未捕获的异常。 This is very important for long running node.JS servers since a single uncaught exception can bring the whole server down. 这对于长时间运行的node.JS服务器非常重要,因为单个未捕获的异常会导致整个服务器宕机。

Furthermore, you can use Step to control execution of scripts to have a clean up section as the last step. 此外,您可以使用“步骤”来控制脚本的执行,以将清理部分作为最后一步。 For example if you want to write a build script in Node and report how long it took to write, the last step can do that (rather than trying to dig out the last callback). 例如,如果您想在Node中编写一个构建脚本并报告编写花费了多长时间,那么最后一步可以做到这一点(而不是尝试挖掘出最后一个回调)。


#3楼

如果要在Ubuntu(Upstart)中使用服务:将节点作为服务在Ubuntu 11.04中使用upstart,monit和forever.js。


#4楼

One instance where using a try-catch might be appropriate is when using a forEach loop. 在使用forEach循环时,使用try-catch可能更合适。 It is synchronous but at the same time you cannot just use a return statement in the inner scope. 它是同步的,但同时不能只在内部作用域中使用return语句。 Instead a try and catch approach can be used to return an Error object in the appropriate scope. 相反,可以使用“尝试并捕获”方法来返回适当范围内的Error对象。 Consider: 考虑:

function processArray() {
    try { 
       [1, 2, 3].forEach(function() { throw new Error('exception'); }); 
    } catch (e) { 
       return e; 
    }
}

It is a combination of the approaches described by @balupton above. 它是上述@balupton描述的方法的组合。


#5楼

I wrote about this recently at http://snmaynard.com/2012/12/21/node-error-handling/ . 我最近在http://snmaynard.com/2012/12/21/node-error-handling/上撰写了有关此内容的文章。 A new feature of node in version 0.8 is domains and allow you to combine all the forms of error handling into one easier manage form. 域0.8版中节点的一项新功能是域,它使您可以将所有错误处理形式组合为一个更易于管理的形式。 You can read about them in my post. 您可以在我的文章中阅读有关它们的信息。

You can also use something like Bugsnag to track your uncaught exceptions and be notified via email, chatroom or have a ticket created for an uncaught exception (I am the co-founder of Bugsnag). 您还可以使用Bugsnag之类的东西来跟踪未捕获的异常,并通过电子邮件,聊天室收到通知,或者为未捕获的异常创建票证(我是Bugsnag的共同创始人)。


#6楼

nodejs domains is the most up to date way of handling errors in nodejs. nodejs域是处理nodejs中错误的最新方法。 Domains can capture both error/other events as well as traditionally thrown objects. 域可以捕获错误/其他事件以及传统上抛出的对象。 Domains also provide functionality for handling callbacks with an error passed as the first argument via the intercept method. 域还提供了处理回调的功能,该回调具有通过intercept方法作为第一个参数传递的错误。

As with normal try/catch-style error handling, is is usually best to throw errors when they occur, and block out areas where you want to isolate errors from affecting the rest of the code. 与正常的try / catch样式错误处理一样,通常最好在错误发生时抛出错误,并排除希望隔离错误以免影响其余代码的区域。 The way to "block out" these areas are to call domain.run with a function as a block of isolated code. “屏蔽”这些区域的方法是调用domain.run,该函数具有作为隔离代码块的功能。

In synchronous code, the above is enough - when an error happens you either let it be thrown through, or you catch it and handle there, reverting any data you need to revert. 在同步代码中,以上内容就足够了-发生错误时,要么抛出该错误,要么捕获该错误并在那里进行处理,然后还原所有需要还原的数据。

try {  
  //something
} catch(e) {
  // handle data reversion
  // probably log too
}

When the error happens in an asynchronous callback, you either need to be able to fully handle the rollback of data (shared state, external data like databases, etc). 当错误发生在异步回调中时,您要么需要能够完全处理数据回滚(共享状态,诸如数据库之类的外部数据等)。 OR you have to set something to indicate that an exception has happened - where ever you care about that flag, you have to wait for the callback to complete. 或者,您必须设置一些东西来指示发生了异常-无论您关心该标志的位置如何,都必须等待回调完成。

var err = null;
var d = require('domain').create();
d.on('error', function(e) {
  err = e;
  // any additional error handling
}
d.run(function() { Fiber(function() {
  // do stuff
  var future = somethingAsynchronous();
  // more stuff

  future.wait(); // here we care about the error
  if(err != null) {
    // handle data reversion
    // probably log too
  }

})});

Some of that above code is ugly, but you can create patterns for yourself to make it prettier, eg: 上面的一些代码很丑陋,但是您可以自己创建模式使其更漂亮,例如:

var specialDomain = specialDomain(function() {
  // do stuff
  var future = somethingAsynchronous();
  // more stuff

  future.wait(); // here we care about the error
  if(specialDomain.error()) {
    // handle data reversion
    // probably log too
  } 
}, function() { // "catch"
  // any additional error handling
});

UPDATE (2013-09): 更新(2013-09):

Above, I use a future that implies fibers semantics , which allow you to wait on futures in-line. 上面,我使用了隐含fibre语义的future,它使您可以在线等待future。 This actually allows you to use traditional try-catch blocks for everything - which I find to be the best way to go. 实际上,这使您可以对所有内容使用传统的try-catch块-我认为这是最好的方法。 However, you can't always do this (ie in the browser)... 但是,您不能总是这样做(即在浏览器中)...

There are also futures that don't require fibers semantics (which then work with normal, browsery JavaScript). 还有一些期货不需要纤维语义(然后可以使用普通的浏览器JavaScript)。 These can be called futures, promises, or deferreds (I'll just refer to futures from here on). 这些可以称为期货,承诺或递延(从现在开始,我仅指期货)。 Plain-old-JavaScript futures libraries allow errors to be propagated between futures. 普通的JavaScript期货库允许在期货之间传播错误。 Only some of these libraries allow any thrown future to be correctly handled, so beware. 这些库中只有一些库允许正确处理所有抛出的将来,因此请当心。

An example: 一个例子:

returnsAFuture().then(function() {
  console.log('1')
  return doSomething() // also returns a future

}).then(function() {
  console.log('2')
  throw Error("oops an error was thrown")

}).then(function() {
  console.log('3')

}).catch(function(exception) {
  console.log('handler')
  // handle the exception
}).done()

This mimics a normal try-catch, even though the pieces are asynchronous. 即使片段是异步的,这也模仿了普通的try-catch。 It would print: 它会打印:

1
2
handler

Note that it doesn't print '3' because an exception was thrown that interrupts that flow. 请注意,它不会显示“ 3”,因为引发了异常,从而中断了该流程。

Take a look at bluebird promises: 看看蓝鸟的承诺:

Note that I haven't found many other libraries other than these that properly handle thrown exceptions. 请注意,除了可以正确处理引发的异常的库以外,我没有找到其他许多库。 jQuery's deferred, for example, don't - the "fail" handler would never get the exception thrown an a 'then' handler, which in my opinion is a deal breaker. 举例来说,jQuery的延迟就不会-“失败”处理程序永远不会将引发“ then”处理程序的异常抛出,在我看来,这是一个破坏交易的行为。

发布了0 篇原创文章 · 获赞 137 · 访问量 84万+

猜你喜欢

转载自blog.csdn.net/xfxf996/article/details/105453838