Node.js + Express.js 应用的错误处理原则?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7151487/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 14:29:41  来源:igfitidea点击:

Error handling principles for Node.js + Express.js applications?

node.jsexpress

提问by Clint Harris

It seems like error reporting/handling is done differently in Node.js+Express.jsapplications compared to other frameworks. Am I correct in understanding that it works as follows?

与其他框架相比,Node.js+ Express.js应用程序中的错误报告/处理方式似乎有所不同。我是否正确理解它的工作原理如下?

A)Detecterrors by receiving them as parameters to your callback functions. For example:

A)通过接收错误作为回调函数的参数来检测错误。例如:

doSomethingAndRunCallback(function(err) { 
    if(err) { … }
});

B)Reporterrors in MIDDLEWARE by calling next(err). Example:

B)通过调用 next(err)报告MIDDLEWARE 中的错误。例子:

handleRequest(req, res, next) {
    // An error occurs…
    next(err);
}

C)Reporterrors in ROUTES by throwing the error. Example:

C)通过抛出错误来报告ROUTES 中的错误。例子:

app.get('/home', function(req, res) {
    // An error occurs
    throw err;
});

D)Handleerrors by configuring your own error handler via app.error() or use the generic Connect error handler. Example:

d)手柄通过配置通过app.error自己的错误处理的错误()或使用通用连接错误处理程序。例子:

app.error(function(err, req, res, next) {
    console.error(err);
    res.send('Fail Whale, yo.');
});

Are these four principles the basis for all error handling/reporting in Node.js+Express.js applications?

这四个原则是否是 Node.js+Express.js 应用程序中所有错误处理/报告的基础?

回答by Raynos

Error handling in Node.js is generally of the format A). Most callbacks return an error object as the first argument or null.

Node.js 中的错误处理通常采用 A) 格式。大多数回调返回一个错误对象作为第一个参数 or null

Express.js uses middleware and the middleware syntax uses B) and E) (mentioned below).

Express.js 使用中间件,中间件语法使用 B) 和 E)(如下所述)。

C) is bad practice if you ask me.

C) 如果你问我,这是不好的做法。

app.get('/home', function(req, res) {
    // An error occurs
    throw err;
});

You can easily rewrite the above as

您可以轻松地将上述内容重写为

app.get('/home', function(req, res, next) {
    // An error occurs
    next(err);
});

Middleware syntax is valid in a getrequest.

中间件语法在get请求中有效。

As for D)

至于 D)

(07:26:37 PM) tjholowaychuk: app.error is removed in 3.x

(07:26:37 PM) tjholowaychuk:app.error 在 3.x 中被删除

TJ just confirmed that app.erroris deprecated in favor of E

TJ 刚刚确认app.error已弃用 E

E)

E)

app.use(function(err, req, res, next) {
  // Only handle `next(err)` calls
});

Any middleware that has a length of 4 (4 arguments) is considered error middleware. When one calls next(err)connect goes and calls error-based middleware.

任何长度为 4(4 个参数)的中间件都被视为错误中间件。当一个调用next(err)connect 并调用基于错误的中间件时。

回答by hthserhs

People at Joyent have published a really insightful best-practices documenton this. A must-read article for any Node.js developer.

Joyent 的人发布了一份非常有见地的最佳实践文档。任何 Node.js 开发人员的必读文章。

回答by David

Why first-parameter?

为什么是第一个参数?

Because of the asynchronous nature of Node.js, the first-parameter-as-errpattern has become well established as a convention for userland Node.js error handling. This is because asynchronous:

由于 Node.js 的异步特性,first-parameter-as-err模式已经成为用户级 Node.js 错误处理的约定。这是因为异步:

try {
    setTimeout(function() {
        throw 'something broke' //Some random error
    }, 5)
}
catch(e) {
   //Will never get caught
}

So instead having the first argument of the callback is pretty much the only sensible way to pass errors asynchronously other than just throwing them.

因此,拥有回调的第一个参数几乎是异步传递错误的唯一明智方法,而不仅仅是抛出它们。

To do so will result in an unhandled exceptionwhich, just in the way it sounds, implies that nothing was done to get the application out of its confused state.

这样做将导致一个unhandled exception,就像听起来那样,暗示没有采取任何措施使应用程序摆脱其混乱状态。

Exceptions, why do they exist

异常,它们为什么存在

It is worth noting however, that virtually all part of Node.js are event-emitters and the throwing of an exception is a low-level event which can be handled like all events:

然而值得注意的是,Node.js 的几乎所有部分都是事件发射器,抛出异常是一个低级事件,可以像所有事件一样处理:

//This won't immediately crash if connection fails
var socket = require("net").createConnection(5000);
socket.on("error", function(err) {
    console.error("calm down...", err)
});

This can-but-shouldn'tbe taken to the extreme to catch all errorsand make an application which will try very hard to never crash. This is a terrible idea in nearly every use-case, because it will leave the developer without any idea of what's going on in the application state and is analogous to wrapping main in try-catch.

不能但不应该采取极端措施来捕获所有错误并制作一个将非常努力地永不崩溃的应用程序。这几乎在每个用例中都是一个糟糕的想法,因为它会让开发人员不知道应用程序状态中发生了什么,并且类似于在 try-catch 中包装 main。

Domains - grouping events logically

域 - 逻辑分组事件

As part of dealing with this problem of exceptions making applications fall over, domainsallow the developer to take, for example the Express.js application, and try and close off connections sensibly in the event of catastrophic failure.

作为处理导致应用程序失败的异常问题的一部分,允许开发人员采用例如 Express.js 应用程序,并在发生灾难性故障时尝试并明智地关闭连接。

ES6

ES6

It's probably mentioning that this will change again as ES6 allows the generator pattern to create asynchronous events which are still catchable with try/catch blocks.

它可能提到这将再次改变,因为 ES6 允许生成器模式创建异步事件,这些事件仍然可以被 try/catch 块捕获。

Koa (written by TJ Holowaychuck, same original author of Express.js) noticeably does this. It uses the ES6 yieldstatement to create blocks that, while appearing nearly syncronous, are handled in the usual node asynchronous fashion:

Koa(由 TJ Holowaychuck 编写,与 Express.js 的原作者相同)明显地做到了这一点。它使用 ES6yield语句创建块,虽然看起来几乎同步,但以通常的节点异步方式处理:

app.use(function *(next) {
    try {
        yield next;
    } 
    catch (err) {
        this.status = err.status || 500;
        this.body = err.message;
        this.app.emit('error', err, this);
    }
});

app.use(function *(next) {
    throw new Error('some error');
})

This example was shamelessly stolen from here.

这个例子是从这里无耻地偷来的