如何处理node.js中的代码exception?

我经历了Express的文档, 描述error handling的部分对我来说是完全不透明的。

我想他们所指的app是一个实例createServer() ,对不对? 但是我不知道如何在处理请求的过程中发生exception时阻止node.js炸毁应用程序进程。

我真的不需要任何幻想; 我只想返回一个500的状态,加上一个空的响应,只要有exception。 节点进程不能因为某处存在未捕获的exception终止。

有一个简单的例子,如何实现这一目标?


 var express = require('express'); var http = require('http'); var app = express.createServer(); app.get('/', function(req, res){ console.log("debug", "calling") var options = { host: 'www.google.com', port: 80, path: "/" }; http.get(options, function(response) { response.on("data", function(chunk) { console.log("data: " + chunk); chunk.call(); // no such method; throws here }); }).on('error', function(e) { console.log("error connecting" + e.message); }); }); app.configure(function(){ app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); }); app.listen(3000); 

崩溃整个应用程序,产生回溯

 mypath/tst.js:16 chunk.call(); // no such method; throws here ^ TypeError: Object ... has no method 'call' at IncomingMessage.<anonymous> (/Library/WebServer/Documents/discovery/tst.js:16:18) at IncomingMessage.emit (events.js:67:17) at HTTPParser.onBody (http.js:115:23) at Socket.ondata (http.js:1150:24) at TCP.onread (net.js:374:27) 

如果您确实想要捕获所有exception并提供一些处理,而不是退出Node.js进程,则需要处理Node的uncaughtException事件。

如果你仔细想想,这是一个Node的东西,而不是一个Express的东西,因为如果你从一些任意的代码中抛出一个exception,Express不能保证也不会看到它,或者有能力去捕捉它。 (为什么呢?exception与Nodetypes的asynchronous事件驱动的callbacky代码不能很好的交互,exception会在调用堆栈中find一个catch()块,这个块在抛出exception的时候处于范围之内如果myFunction推迟有些工作是在某个事件发生时运行的callback函数,然后返回到事件循环,然后当该callback函数被调用时,直接从主事件循环中调用,并且myFunction不再位于调用堆栈上;如果该callback函数函数抛出一个exception,即使myFunction有一个try / catch块,它也不会捕获exception。)

这在实践中意味着如果你抛出一个exception,而不是自己捕获它,而你在一个被Express直接调用的函数中这样做,Express可以捕获exception并调用你安装的error handling器,假设你configuration了一些error handling中间件,如app.use(express.errorHandler()) 。 但是,如果您在为响应asynchronous事件而调用的函数中抛出相同的exception,则Express将无法捕获它。 (唯一的方法是通过监听全局Node uncaughtException事件,这首先是一个坏主意,因为这是全局的,您可能需要将其用于其他事情,其次,因为Express将不知道请求是什么与例外相关)。

这是一个例子。 我将这个路由处理代码片段添加到现有的Express应用程序中:

 app.get('/fail/sync', function(req, res) { throw new Error('whoops'); }); app.get('/fail/async', function(req, res) { process.nextTick(function() { throw new Error('whoops'); }); }); 

现在,如果我在浏览器中访问http://localhost:3000/fail/sync ,浏览器将转储一个调用堆栈(显示express.errorHandler正在执行)。 如果我在浏览器中访问http://localhost:3000/fail/async ,浏览器会生气(Chrome会显示“No data received:Error 324,net :: ERR_EMPTY_RESPONSE:服务器closures连接而不发送任何数据“消息),因为Node进程已经退出,在我调用它的terminal的stdout上显示回溯。

为了能够捕获asynchronous错误,我使用域。 有了Express,你可以试试这个代码:

 function domainWrapper() { return function (req, res, next) { var reqDomain = domain.create(); reqDomain.add(req); reqDomain.add(res); res.on('close', function () { reqDomain.dispose(); }); reqDomain.on('error', function (err) { next(err); }); reqDomain.run(next) } } app.use(domainWrapper()); //all your other app.use app.use(express.errorHandler()); 

这段代码会让你的asynchronous错误被捕获并发送到你的error handling程序。 在这个例子中,我使用了express.errorHandler,但它可以与任何处理程序一起使用。

有关域的更多信息: http : //nodejs.org/api/domain.html

您可以使用表示使用的默认error handling程序,它实际上是连接error handling程序 。

 var app = require('express').createServer(); app.get('/', function(req, res){ throw new Error('Error thrown here!'); }); app.configure(function(){ app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); }); app.listen(3000); 

更新对于你的代码,你实际上需要捕获错误,并通过它来expression这样的

 var express = require('express'); var http = require('http'); var app = express.createServer(); app.get('/', function (req, res, next) { console.log("debug", "calling"); var options = { host:'www.google.com', port:80, path:"/" }; http.get(options, function (response) { response.on("data", function (chunk) { try { console.log("data: " + chunk); chunk.call(); // no such method; throws here } catch (err) { return next(err); } }); }).on('error', function (e) { console.log("error connecting" + e.message); }); }); app.configure(function () { app.use(express.errorHandler({ dumpExceptions:true, showStack:true })); }); app.listen(3000);