下面的代码是在一个Express 4.0路由器中。我故意给出了一个错误的SELECT语句(表不存在)。 clientErrorHandler()按预期调用,然后Node退出(崩溃)。 由于DB调用的异步性质,添加try / catch没有帮助。 当我纠正SELECT语句时,一切都按预期工作。
router.use(function (req, res, next){
DBCon.DBConUtil.pool.getConnection(function(err, connection){
if (err) throw new DBDataError("Error while getting connection from pool");
connection.query('SELECT * FROM employee' ,function(err,rows){
if(err){
connection.release();
throw new DBDataError("Error while executing select statement using pool connection.");
}else{
res.rows1 = rows;
logger.info("App-Instance-name: %s, filename: %s, MessageContent: %s", process.env.NODE_APP_INSTANCE, __filename, JSON.stringify({message: "Data received from Db using connection pool: ", data: rows}));
connection.release();
}
});
});
res.send(JSON.stringify(res.rows1));
//next();
});
router.use(clientErrorHandler);
router.use(errorHandler);
function clientErrorHandler(err, req, res, next) {
logger.info("App-Instance-name: %s, filename: %s, Cookies: %s", process.env.NODE_APP_INSTANCE, __filename, JSON.stringify(req.cookies));
logger.info("App-Instance-name: %s, filename: %s, stack trace: ", process.env.NODE_APP_INSTANCE, __filename, err.stack);
return next(err);
}
function errorHandler(err, req, res, next) {
res.status(500);
res.send('Error in handing DB calls.');
}
function DBDataError(message) {
this.constructor.prototype.__proto__ = Error.prototype
Error.captureStackTrace(this, this.constructor)
this.name = this.constructor.name
this.message = message
}
另外两个信息: -
(1)如果在“if(err)”之外没有实际DB错误时抛出相同的DBDataError,则会按预期调用clientErrorHandler(),并且节点不会退出。这表明脚本能够按预期抛出并捕获错误。
(2)如果使用“if(err)”捕获DB错误并且我没有抛出新的DBDataError,则不会调用clientErrorHandler(),这也是预期的行为,节点不会退出。这表明由于数据库异常,节点没有崩溃。
任何专家都可以对此有所了解。
感谢。
答案 0 :(得分:0)
也许你应该多读一些关于JavaScript和回调的信息,因为你的res.send不在回调中。
调用的函数的顺序(在router.use回调开始之后),假设是非错误流
以下任何一项都应该解决它:
1:
router.use(function (req, res, next){
DBCon.DBConUtil.pool.getConnection(function(err, connection){
if (err) throw new DBDataError("Error while getting connection from pool");
connection.query('SELECT * FROM employee' ,function(err,rows){
if(err){
connection.release();
throw new DBDataError("Error while executing select statement using pool connection.");
res.send(JSON.stringify({error: 'DB error'}));
}else{
res.rows1 = rows;
logger.info("App-Instance-name: %s, filename: %s, MessageContent: %s", process.env.NODE_APP_INSTANCE, __filename, JSON.stringify({message: "Data received from Db using connection pool: ", data: rows}));
connection.release();
res.send(JSON.stringify(res.rows1));
}
});
});
//next();
});
2(更好的一个):
router.use(function (req, res, next){
DBCon.DBConUtil.pool.getConnection(function(err, connection){
if (err) throw new DBDataError("Error while getting connection from pool");
connection.query('SELECT * FROM employee' ,function(err,rows){
if(err){
connection.release();
throw new DBDataError("Error while executing select statement using pool connection.");
}else{
res.rows1 = rows;
logger.info("App-Instance-name: %s, filename: %s, MessageContent: %s", process.env.NODE_APP_INSTANCE, __filename, JSON.stringify({message: "Data received from Db using connection pool: ", data: rows}));
connection.release();
}
// Let express know this callback is done and it can resume the middleware process
next();
});
});
});
最后注意:请不要在中间件中使用res.send!