var express = require("express"); var app = express(); app.use(app.router); //express error handler (never called) app.use(function(err,req,res,next) { console.log(err); res.send(500); }); app.get("/test",function(req,next) { require("fs").readFile("/some/file",function(err,data) { a.b(); //blow up }); }); app.listen(8888);
在上面的代码中,行a.b()抛出“ReferenceError:a is not defined”异常.永远不会调用定义的错误处理程序.请注意,fs.readFile()返回的错误对象在这种情况下为null,因为文件已正确读取.错误是异步处理程序中的代码.
我已经阅读了有关使用node的uncaughtExpception的this post,但the documentation说不使用该方法.即使我确实使用过它,我如何将500响应发送回用户?我不再使用快速响应对象了.
那么你如何处理这种情况?
解决方法
简短的回答:正确的做法是已经发生的事情:您的程序应该打印堆栈跟踪并退出并显示错误.
潜在的想法:
所以我认为你需要考虑不同类别的错误.我的第一个答案是处理数据相关的错误,这是一个编写良好的程序可以并且应该干净利落地处理.你所描述的是一个CRASH.如果您阅读了链接到的node.js文档,那么它是正确的.此程序在此时可以执行的唯一有用的事情是使用堆栈跟踪退出并允许进程主管重新启动它并获得理解状态.一旦程序崩溃,由于极其广泛的错误可能是异常进入堆栈顶部的根本原因,它基本上是不可恢复的.在您的具体示例中,每次都会继续发生此错误,直到修复源代码错误并重新部署应用程序.如果您担心未经测试和错误的代码将进入您的应用程序,添加更多未经测试和错误的错误处理代码并不能解决正确的问题.
但简而言之,不,没有办法获得引起此异常的HTTP请求对象的引用,因此AFAIK无法改变最终用户在浏览器中感知的方式,而不是在中间反向代理层处理此问题您可以在哪里配置原始超时并发送更友好的错误页面(对于任何不是完整HTML文档的请求,这当然是无用的).
节点中的错误处理圣经
在我看来,Dave Pacheco的Error Handling in Node.js是关于这个主题的权威性工作.它是全面,广泛和彻底的.我建议定期阅读和重新阅读.
要解决@asparagino的评论,如果一个未处理的异常很容易重现或高频率发生,那不是一个边缘情况,这是一个错误.正确的做法是改进代码,以便在面对这种情况时不会生成未捕获的异常.实际上处理条件,从而将程序员错误转换为操作错误,并且程序可以继续而无需重新启动且没有未捕获的异常.