首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >捕获错误的NodeJS最佳实践

捕获错误的NodeJS最佳实践
EN

Stack Overflow用户
提问于 2017-03-05 17:36:59
回答 4查看 7.6K关注 0票数 1

我要开始做w/ NodeJS和快递了。来自其他流行的脚本语言和C++背景,异步调用DB函数有点陌生。我已经整理出了一个模式,但我仍然对捕获异常感到好奇。下面是我的基本模式。

代码语言:javascript
复制
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');
};

一般来说,我有很多端点和回调。但是,我有点不知道我在哪里设置了“尝试/捕捉”块来捕捉回调中抛出的错误。我四处寻找一些建议,但很多建议似乎都在使用的web框架上(如果有的话)。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-03-05 18:17:44

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

基本上,对于如何处理错误,您有几种选择。您可以在每个端点中完全正确地处理它,并发送某种错误响应。

在每个错误点发送响应

代码语言:javascript
复制
app.get('/', function(req, res) {
    // do stuff
    connection.query(queryString, function(err,result){
        if (err) return res.status(500).send(someErrorResponse);
        // process results.
    };
});

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

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

代码语言:javascript
复制
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)
});

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

使用承诺收集每个路由中的错误。

如果您正在使用涉及更多的异步操作序列,其中可能有多个异步操作被排序在一起,那么在每个异步操作中处理错误都会很痛苦。在这里,在所有异步操作中使用承诺更容易地允许所有错误在每个路由的顶层渗出最多一个.catch()语句。你没有说你使用的是什么数据库,但这里有一个想法,那是什么样子。总的思想是,您可以编写代码,以便所有承诺的拒绝(例如错误)将在每个路由处理程序中传播到最多一个中央.catch(),然后您可以从该.catch()调用next(err),将错误发送到集中式错误处理程序。下面是针对一个数据库操作的最新版本的Mongoose (您没有说您使用的是哪个数据库)。

代码语言:javascript
复制
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)
});

如果您有多个操作,下面是这样的情况:

代码语言:javascript
复制
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)
});

由于ES6内置于对承诺的支持,而ES7将增加对异步操作的支持(这是基于承诺的),并且所有提供异步操作的重要库都增加了或正在添加对承诺的支持,因此很明显,承诺是管理异步操作的语言的未来。这将是我的强烈建议。

票数 9
EN

Stack Overflow用户

发布于 2017-03-05 17:57:16

您永远不要抛出这样的错误!:)原因是,在某一时刻,您的整个节点应用程序将停止工作,因为一些db查询失败。这件事应该处理,而不是等死。

因为这是一个route处理程序--处理用户正在获取的特定url (例如/),所以应该有一些输出。如果存在无法处理的错误,或者可能导致内部状态混乱,则始终可以显示一个具有状态500的页面和一个很好的设计。

因此,基本上没有什么事情发生-返回任何类型的respones,甚至render一个页面,但提供信息,什么地方出了问题。

另外,一个常见的场景是类似于Alon所介绍的内容。快递中的所有路由实际上都是一个中间件功能,一个接一个地被调用。如果该路由与请求的路由不匹配,则函数将跳过,然后调用下一个路由。你可以手动控制。路由器的实际模式如下:

代码语言:javascript
复制
app.get('/', function(req, res, next) {
    // you can have the request
    // you can send response like res.send('hello')
    // OR you can skip this function using NEXT
});

next的实际签名是next(err)。因此,如果您在没有任何参数的情况下调用它,它将跳到下一个中间件。如果使用参数调用它,它将跳过所有常规函数,转到堆栈中的最后一个函数,或者更具体地说,那些处理错误的函数。它们就像普通的一样,,但采用四个参数,而不是三个:

代码语言:javascript
复制
app.use(function (err, req, res, next) { });

如果您使用参数调用next,那么理解此函数将被调用是非常重要的。扔一个错误不会有任何好处!当然,如果您的路由没有一个符合特定的标准(url),那么调用中的最后一个将被调用,所以您仍然可以处理"not“错误。

这是一个常见的场景,您将使用:

代码语言:javascript
复制
// development error handler, will print stacktrace
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        debug('ERROR [ip: %s]:: dev env -> ', req.ip, err); // I'm using debug library - very helpful
        res.status(err.status || 500);
        res.render('deverr', { // I render custom template with the whole stack beautifully displayed
            errMessage: err.message,
            error: err
        });
    });
}

// production error handler, no stacktraces leaked to user
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('pages/error', { // custom error page with nice design and a message
        errMessage: err.message,
        error: {}
    });
});

希望这会有所帮助!)

票数 3
EN

Stack Overflow用户

发布于 2017-03-05 17:55:02

由于您使用的是express,所以它有自己的处理异常的方法,定义如下:

代码语言:javascript
复制
function clientErrorHandler (err, req, res, next) {
    if (req.xhr) {
        res.status(500).send({ error: 'Something failed!' })
    } else {
        next(err)
    }
}
app.use(clientErrorHandler)

有关详细信息,请访问:

https://expressjs.com/en/guide/error-handling.html

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42611707

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档