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

与其他框架相比,Node.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 应用程序中所有错误处理/报告的基础吗?

41723 次浏览

Js 中的错误处理通常是格式 A)。大多数回调将错误对象作为第一个参数或 null返回。

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)连接去和调用基于错误的中间件。

Joyent 的人已经就此发布了 一份真正有见地的最佳实践文件,这是任何一个 Node.js 开发者都必须阅读的文章。

为什么是第一参数?

由于 Node.js 的异步特性,第一参数误差模式已经作为 Js 错误处理的约定得到了很好的确立。这是因为异步性:

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

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

这样做将导致 unhandled exception,就像它听起来的那样,意味着没有做任何事情来使应用程序摆脱其混乱状态。

例外,为什么会存在

但是值得注意的是,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)
});

这个 不能但不应该被采取到极端的 捕捉所有错误和作出一个应用程序,将尽力从来没有崩溃。几乎在每个用例中,这都是一个糟糕的想法,因为它会让开发人员不知道应用程序状态中发生了什么,类似于在 try-catch 中包装 main。

域-逻辑分组事件

作为处理异常导致应用程序崩溃这一问题的一部分,域名允许开发人员使用 Express.js 应用程序,并在发生灾难性故障时合理地尝试关闭连接。

ES6

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

Koa (由 Express.js 的原作者 TJ Holowaychuck 编写)明显做到了这一点。它使用 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');
})

这个例子是无耻地从 给你偷来的。