Node.js 包装抛出的错误,以便它们不会';t使节点Web服务器崩溃(节点mongodb本机)

Node.js 包装抛出的错误,以便它们不会';t使节点Web服务器崩溃(节点mongodb本机),node.js,exception-handling,error-handling,node-mongodb-native,Node.js,Exception Handling,Error Handling,Node Mongodb Native,简化代码。。。但基本情况是,我正在使用Mongo执行findOne查询以查找用户,但如果用户不存在,则会抛出一个错误,使整个Web服务器崩溃。有人能给我指出正确的方向,正确地包装这些错误,这样他们就不会把所有的事情都搞糟了吗 路线: server.get('/v1/user/:token', function(req,res){ console.log("user endpoint hit"); var user = users.findOne({token:req.params

简化代码。。。但基本情况是,我正在使用Mongo执行findOne查询以查找用户,但如果用户不存在,则会抛出一个错误,使整个Web服务器崩溃。有人能给我指出正确的方向,正确地包装这些错误,这样他们就不会把所有的事情都搞糟了吗

路线:

server.get('/v1/user/:token', function(req,res){
    console.log("user endpoint hit");
    var user = users.findOne({token:req.params.token}, function(err,user){
        if (user) {
            res.json({token:user.token,credits:user.credits,subscribed:user.subscribed,searches:user.searches});
        } else {
            console.log("DB error in lookup user");
            throw new DBError("Error looking up user in get endpoint");
        }
    });
});
DBError声明:

function DBError(msg) {
    this.name = "DBError";
    console.log("DBError " + msg);
    Error.call(this,msg);
    Error.captureStackTrace(this, arguments.callee);
}
下面是处理错误的块:

server.error(function(err, req, res, next){
    if (err instanceof NotFound) {
        res.send(404,{error: "404 Not Found"});
    }
    else if (err instanceof DBError) {
        res.send(400, {error: "Database error"});
    } else {
        res.send(500,{error:"500 internal error"});
    }
});
现在,当我运行单元测试时,这里是stacktrace,它将结束服务器进程(不理想!):


一般来说,您不会抛出错误。当出现严重错误时,错误应该会关闭进程/工作进程。我不认为在上面的代码中找不到一个用户犯了非常严重的错误,但是根据你的具体情况肯定是不可能发生的。 但是,当您需要处理错误时,[需要引用]最普遍的方式是将其作为回调中的第一个参数传递(正如您在
findOne()
的回调中所看到的)。在express中,它使用中间件中的第三个参数(称为
next
)和错误处理程序来完成。例如:

您的路线:

server.get('/v1/user/:token', function(req,res,next){
    console.log("user endpoint hit");
    var user = users.findOne({token:req.params.token}, function(err,user){
        if (user) {
            res.json({token:user.token,credits:user.credits,subscribed:user.subscribed,searches:user.searches});
        } else {
            next(new DBError("Error looking up user in get endpoint"));
        }
    });
});
指定使用中间件的位置:

app.use(function(err, req, res, next){
  // This will handle all errors sent through next()
  console.error(err.stack);
  res.send(500, 'Something broke!');
});

此外,您可能还需要查看节点中的。该页面还涉及如何正确响应错误。

感谢您提供的详细答案,我现在就来试一试。但是有一个问题,为什么我的404和500错误不能同时停止服务器?它们使用的是相同的“抛出”机制,不是吗?实际上从未抛出错误,只是创建了一个错误对象并将其传递给next()。如果next出现错误,express将中止中间件链并调用任何错误处理程序,如果错误如此严重,您可以选择抛出错误(或者按照上面链接的域页面上的建议,优雅地关闭工作进程),或者选择只向其关注的客户端发送消息。
app.use(function(err, req, res, next){
  // This will handle all errors sent through next()
  console.error(err.stack);
  res.send(500, 'Something broke!');
});