几天前我刚开始试用node.js。我已经意识到,每当我的程序中出现未处理的异常时,节点就会终止。这与我所接触的正常服务器容器不同,在正常服务器容器中,当发生未处理的异常时,只有工作线程死亡,并且容器仍然能够接收请求。这引发了几个问题:

process.on('ncaughtException')是防范它的唯一有效方法吗?process.on('ncaughtException')是否也会在异步进程执行期间捕获未处理的异常?是否有一个已经构建好的模块(例如发送电子邮件或写入文件),我可以在未捕获的异常情况下利用它?

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


当前回答

前段时间读了这篇文章后,我想知道在api/函数级别上使用域进行异常处理是否安全。我想用它们来简化我编写的每个异步函数中的异常处理代码。我担心的是,为每个函数使用一个新域会引入大量开销。我的作业似乎表明开销最小,而且在某些情况下,域的性能实际上比try-catch要好。

http://www.lighthouselogic.com/#/using-a-new-domain-for-each-async-function-in-node/

其他回答

如果你想在Ubuntu中使用服务(Upstart):在Ubuntu 11.04中使用节点作为服务,包括Upstart、monit和forever.js

我只想补充一点,Step.js库通过始终将其传递给下一步函数来帮助您处理异常。因此,作为最后一步,您可以使用一个函数来检查前面任何步骤中的任何错误。这种方法可以大大简化错误处理。

下面是github页面的引用:

抛出的任何异常都会被捕获并作为第一个参数传递给下一个函数。只要不内联嵌套回调函数你的主要功能,这可以防止任何未完成的任务例外情况。这对于长期运行的node.JS服务器非常重要因为一个未捕获的异常会导致整个服务器停机。

此外,您可以使用步骤来控制脚本的执行,以便将清理部分作为最后一步。例如,如果您想在Node中编写一个构建脚本并报告编写所需的时间,那么最后一步可以做到这一点(而不是试图挖掘最后一个回调)。

使用try-catch可能比较合适的一个例子是使用forEach循环。它是同步的,但同时不能只在内部范围中使用return语句。相反,可以使用try-and-catch方法在适当的范围内返回Error对象。考虑:

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

这是上面@balupton描述的方法的组合。

这里已经很好地讨论了捕获错误,但值得记住的是将错误记录在某个位置,以便您可以查看它们并修复它们。

​Bunyan是NodeJS的一个流行日志框架,它支持向一系列不同的输出位置进行输出,这使得它对本地调试非常有用,只要您避免console.log。​在域的错误处理程序中,可以将错误输出到日志文件中。

var log = bunyan.createLogger({
  name: 'myapp',
  streams: [
    {
      level: 'error',
      path: '/var/tmp/myapp-error.log'  // log ERROR to this file
    }
  ]
});

如果您有大量错误和/或服务器需要检查,这可能会很耗时,因此值得研究Raygun(免责声明,我在Raygun工作)这样的工具来将错误分组在一起,或者将两者同时使用。​如果您决定使用Raygun作为工具,那么设置也非常简单

var raygunClient = new raygun.Client().init({ apiKey: 'your API key' });
raygunClient.send(theError);

​在使用PM2或永久性工具的情况下,你的应用程序应该能够崩溃、注销发生的事情并重新启动,而不会出现任何重大问题。

  getCountryRegionData: (countryName, stateName) => {
    let countryData, stateData

    try {
      countryData = countries.find(
        country => country.countryName === countryName
      )
    } catch (error) {
      console.log(error.message)
      return error.message
    }

    try {
      stateData = countryData.regions.find(state => state.name === stateName)
    } catch (error) {
      console.log(error.message)
      return error.message
    }

    return {
      countryName: countryData.countryName,
      countryCode: countryData.countryShortCode,
      stateName: stateData.name,
      stateCode: stateData.shortCode,
    }
  },