NodeJs捕获异步方法中发生的未处理错误



原来我想问一个关于如何创建基于Node.js的web服务器的问题。然而,这可能是一个非常大而模糊的问题。所以我把它分解成我在创建一个健壮的web服务器时所面临的小而具体的问题或挑战。

所以,我面临的挑战之一是如何在Node.js中捕获所有未处理的错误?我想这样做,因为我不希望任何未处理的错误阻止Node.js运行,导致web服务器关闭。

想到的解决方案是将服务器运行的代码块放在try-catch块中,以捕获所有未处理的错误。然而,如果异步方法发生任何错误,这将不起作用。例如,我的web服务器可能看起来像下面的代码:

var fs = require('fs');
var http = require('http');
try {
    // Here is my main web server, it could happen errors by adding
    // more and more modules and functionalities to my server.
    // I need to catch all unhandled errors to prevent server from crashing
    // So, I put my whole server running in a try-catch block, but any error from
    // an async method could not be caught!
    http.createServer(function(req, res) {
        throw Error("An unhandled error happens!");
    }).listen(1234);
}catch (e){
    console.log("An unhandled error caught!")
}
console.log('Server is listening to port 1234');

所以,我在错误处理的正确方向,以确保服务器没有停止?或者有其他机制使服务器从错误中恢复?

你需要使用域

一个封装所有服务器的全局域,每个请求一个域。如果在初始化过程中出现错误,那么全局域将捕获该错误,然后可以将其记录下来,执行一些清理任务并关闭服务器。如果从请求日志中获得错误,则将其列为最高优先级,并继续为其他请求提供服务。这就是node.js希望我们编写健壮的web服务器的方式。

主要的问题是尽量优雅地关闭。一个优雅的退出意味着当你需要终止服务器(从ctrl-c或sigint或错误或其他),而不是做一个简单的process.exit(1),你必须清理资源,如关闭数据库连接,关闭文件,通知某人,等等。您不能使用process.on("exit", ...),因为当调用处理程序时,事件循环不起作用,您不能执行异步任务。

另外,如果您使用worker,如何在服务器需要关闭时优雅地关闭它们?

如何处理明确的错误?

所有这些东西似乎都很复杂,以确保始终正常关闭。这就是为什么我做了node-grace

在回调函数中使用try/catch:

var fs = require('fs');
var http = require('http');
try {
    http.createServer(function(req, res) {
        try{
            // some code trowing erors
        }catch(e){
             console.log("error: " + e);
        }
}).listen(1234);
}catch (e){
    console.log("An unhandled error caught!")
}
console.log('Server is listening to port 1234');

为什么会这样?异步http回调不运行在同一tick代码设置http服务器回调函数(此外,该函数被调用,每次您的服务器得到请求)。试试你自己:

 try{
      throw Error("An unhandled error happens!");
 }catch(e){
     console.log(e)
 }

:

 try{
     process.nextTick(function(){
        throw Error("An unhandled error happens!")
     });
 }
 catch(e){
     console.log(e)
 }

如果使用Express是您的选项,我建议使用它而不是相当低级的http模块。使用Express,您可以很好地处理错误:

var express = require('express');
var app     = express();
app.get('/', function(req, res) {
  throw Error("An unhandled error happens!");
});
app.use(function(err, req, res, next) {
  console.log('error', err);
  res.send(500); // send a proper HTTP 500 message back to the client
});
app.listen(1234);
console.log('Server is listening to port 1234');

否则,请查看Node

的域模块

最新更新