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

发布于 2024-12-01 02:55:55 字数 917 浏览 1 评论 0 原文

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

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

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

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

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

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

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

D) 通过 app.error() 配置您自己的错误处理程序来处理错误,或者使用通用的 Connect 错误处理程序。示例:

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

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

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

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

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

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

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

C) Report errors in ROUTES by throwing the error. Example:

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

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦在夏天 2024-12-08 02:55:55

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

Express.js 使用中间件,中间件语法使用 B) 和 E)(下面提到)。

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

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

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

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

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

至于D)

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

TJ 刚刚确认 app.error 已被弃用,取而代之的是 E

E)

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

任何长度为 4 的中间件 ( 4 个参数)被视为错误中间件。当调用 next(err) 连接时,它会调用基于错误的中间件。

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

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

C) is bad practice if you ask me.

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 get request.

As for D)

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

TJ just confirmed that app.error is deprecated in favor of 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.

沉溺在你眼里的海 2024-12-08 02:55:55

Joyent 的人员就此发布了一份非常有洞察力的最佳实践文档。所有 Node.js 开发人员必读的文章。

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

余厌 2024-12-08 02:55:55

为什么是第一个参数?

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

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

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

这样做将导致未处理的异常,顾名思义,这意味着没有采取任何措施使应用程序摆脱混乱状态。

异常,为什么它们存在

然而值得注意的是,实际上 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)
});

这个可以-但是-不应该采取极端的方式捕获所有错误并创建一个将努力避免崩溃的应用程序。在几乎所有用例中,这都是一个糟糕的想法,因为它会让开发人员不知道应用程序状态中发生了什么,类似于将 main 包装在 try-catch 中。

域 - 对事件进行逻辑分组

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

ES6

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

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

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');
})

这个示例是从 此处

Why first-parameter?

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

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 exception which, just in the way it sounds, implies that nothing was done to get the application out of its confused state.

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:

//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't be taken to the extreme to catch all errors and 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.

Domains - grouping events logically

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

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.

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文