NodeJS捕获错误的最佳实践

kis*_*tic 1 error-handling node.js express

我开始用NodeJS和Express.来自其他流行的脚本语言和C++背景,异步调用数据库函数有点陌生.我已经整理出一个模式,但我仍然对捕获异常感到好奇.以下是我的基本模式.

var callback = function(req, res) {
    // do stuff
    connection.query(queryString, function(err,result){
        if (err) throw err;
        // process results.
    };
};

var express = require('express');
var app     = express();

app.get('/', callback);
app.listen(3000,function() {
    console.log('listening');
};
Run Code Online (Sandbox Code Playgroud)

通常我有很多端点和回调.我在设置ta try/catch块的地方有点迷失,以捕获回调中抛出的错误.我四处寻找一些建议,但其中很多似乎都在使用Web框架(如果有的话).

jfr*_*d00 9

当您引入异步回调时,异常只会返回到数据库事件处理程序的内部,并且您无法捕获或处理该异常.所以,基本上它根本没有好处.它只会导致您中止对该请求的处理,并且您永远不会对该请求发送响应.

基本上,您有多种选择来处理错误.您可以在每个端点完全处理它并发送某种错误响应.

在每个错误点发送响应

app.get('/', function(req, res) {
    // do stuff
    connection.query(queryString, function(err,result){
        if (err) return res.status(500).send(someErrorResponse);
        // process results.
    };
});
Run Code Online (Sandbox Code Playgroud)

转发到集中式错误处理程序

或者,您可以通过调用next(err)以下命令将错误转发到集中式错误处理程序:

app.get('/', function(req, res, next) {
    // do stuff
    connection.query(queryString, function(err,result){
        // if error, forward it on to our centralized error handler
        if (err) return next(err);
        // process results.
    };
});

// centralized error handler - note how it has four parameters
app.use(function(err, req, res, next) {
    // formulate an error response here
    console.log(err);
    res.status(500).send(someErrorMessage)
});
Run Code Online (Sandbox Code Playgroud)

有关如何在Express中使用通用错误处理程序的更多信息,请参阅Nodejs处理不支持的URL和请求类型.

使用promises收集每条路线中的错误

如果您正在使用更多涉及的异步操作序列,其中您可能有多个异步操作一起排序,那么在每个异步操作中处理错误确实很麻烦.这是使用所有异步操作的promises更容易允许所有错误.catch()在每个路由的顶层渗透最多一个语句的地方.你没有说你正在使用什么数据库,但是这里有一个想法.总的想法是,你可以写你的代码,使所有承诺拒绝(如错误)会传播到一个中心.catch()在每个路由处理程序,然后就可以调用next(err).catch(),发送错误的集中错误处理程序.以下是使用一个数据库操作查找最近版本的Mongoose(您没有说明您正在使用哪个数据库)的方法.

app.get('/', function(req, res, next) {
    // do stuff
    connection.query(queryString).exec().then(function(result){
        // process results.
    }).catch(next);
});

// centralized error handler - note how it has four parameters
app.use(function(err, req, res, next) {
    // formulate an error response here
    console.log(err);
    res.status(500).send(someErrorMessage)
});
Run Code Online (Sandbox Code Playgroud)

而且,如果您有多个操作,这就是它的样子:

app.get('/', function(req, res, next) {
    // do stuff
    connection.query(queryString).exec().then(function(result){
        // process results, then make another query
        // return the promise from this second operaton so both results 
        // and error are chained to the first promise
        return connection.query(...).exec();
    }).then(function(result) {
        // process chained result
    }).catch(next);
});

// centralized error handler - note how it has four parameters
app.use(function(err, req, res, next) {
    // formulate an error response here
    console.log(err);
    res.status(500).send(someErrorMessage)
});
Run Code Online (Sandbox Code Playgroud)

由于ES6内置了对promises的支持,ES7将为异步操作(基于promises)添加异步/等待支持,并且所有提供异步操作的重要库都添加或正在添加对promise的支持,很明显,promises是用于管理异步操作的语言的未来.那是我的强烈建议.