error handlingNode.js + Express.js应用程序的原则?
与其他框架相比,Node.js + Express.js应用程序的错误报告/处理似乎有所不同。 我的理解是正确的,它的工作原理如下?
A)通过接收它们作为你的callback函数的参数来检测错误。 例如:
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()configuration自己的error handling程序来处理错误,或者使用通用的Connecterror handling程序。 例:
app.error(function(err, req, res, next) { console.error(err); res.send('Fail Whale, yo.'); });
这四个原则是Node.js + Express.js应用程序中所有error handling/报告的基础吗?
Node.js中的error handling通常是格式A)。 大多数callback函数将返回一个错误对象作为第一个参数或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)
调用next(err)
连接时,调用基于错误的中间件。
Joyent的人们已经发表了一篇非常有见地的最佳实践文档 。 任何Node.js开发人员必读的文章。
为什么是第一个参数?
由于Node.js的asynchronous特性,作为用户级Node.jserror handling的惯例,第一个参数作为err模式已经被很好地build立。 这是因为asynchronous:
try { setTimeout(function() { throw 'something broke' //Some random error }, 5) } catch(e) { //Will never get caught }
因此,除了抛出它们之外,拥有callback的第一个参数几乎是唯一可以asynchronous传递错误的合理方法。
这样做会导致一个unhandled exception
,就像听起来一样,意味着没有任何东西可以让应用程序摆脱困境。
例外,他们为什么存在
但值得注意的是,事实上,Node.js的所有部分都是事件发射器,抛出exception是一个低级事件,可以像所有事件一样处理:
//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中。
域 – 从逻辑上将事件分组
作为处理应用程序崩溃的exception问题的一部分, 域允许开发人员采取(例如)Express.js应用程序,并在发生灾难性故障时尝试closures连接。
ES6
这可能是因为ES6允许生成器模式创build仍然可以被try / catch块捕获的asynchronous事件,这可能会再次改变。
Koa(由TJ Holowaychuck撰写,Express.js的原创作者)显然是这样做的。 它使用ES6 yield
语句来创build块,虽然几乎同步出现,但是以通常的节点asynchronous方式处理:
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'); })
这个例子从这里被无耻地偷走了 。