异步node.js调用中的错误处理

Udo*_*o G 45 javascript exception-handling callback node.js

我是node.js的新手,虽然我对JavaScript非常熟悉.我的问题是关于如何处理node.js中的错误的"最佳实践".

通常在编写Web服务器,FastCGI服务器或各种语言的网页时,我在多线程环境中使用阻塞处理程序的异常.当请求进来时,我通常做这样的事情:

function handleRequest(request, response) {
  try {

    if (request.url=="whatever")
      handleWhateverRequest(request, response);
    else
      throw new Error("404 not found");

  } catch (e) {
    response.writeHead(500, {'Content-Type': 'text/plain'});
    response.end("Server error: "+e.message);
  }
}

function handleWhateverRequest(request, response) {
  if (something) 
    throw new Error("something bad happened");
  Response.end("OK");
}
Run Code Online (Sandbox Code Playgroud)

这样我就可以随时处理内部错误并向用户发送有效响应.

我理解,对于node.js,应该进行非阻塞调用,这显然会导致不同数量的回调,如下例所示:

var sys    = require('sys'),
    fs     = require('fs');

require("http").createServer(handleRequest).listen(8124);

function handleRequest(request, response) {

  fs.open("/proc/cpuinfo", "r",
    function(error, fd) {
      if (error)
        throw new Error("fs.open error: "+error.message);

      console.log("File open.");

      var buffer = new require('buffer').Buffer(10);
      fs.read(fd, buffer, 0, 10, null,
        function(error, bytesRead, buffer) {

          buffer.dontTryThisAtHome();  // causes exception

          response.end(buffer);
        }); //fs.read

    }); //fs.open

}
Run Code Online (Sandbox Code Playgroud)

此示例将完全终止服务器,因为没有捕获异常.我的问题在于,我不能再使用单个try/catch,因此通常无法捕获在处理请求期间可能引发的任何错误.

当然我可以在每个回调中添加一个try/catch,但我不喜欢这种方法,因为这取决于程序员他不会忘记 try/catch.对于具有许多不同和复杂处理程序的复杂服务器,这是不可接受的.

我可以使用全局异常处理程序(防止完整的服务器崩溃),但后来我无法向用户发送响应,因为我不知道哪个请求导致异常.这也意味着请求仍未处理/打开,浏览器将永远等待响应.

有人有一个好的,坚如磐石的解决方案吗?

Sam*_*les 13

Node 0.8引入了一个名为"Domains"的新概念.它们与.net中的AppDomains非常类似,并提供了一种封装一组IO操作的方法.它们基本上允许您将请求处理调用包装在特定于上下文的组中.如果该组抛出任何未捕获的异常,则可以以允许您访问所需的所有范围和上下文特定信息的方式处理和处理它们,以便成功从错误中恢复(如果可能).

这个功能是新的,刚刚引入,所以请谨慎使用,但据我所知,它已被专门用于解决OP试图解决的问题.

可以在以下网址找到文档:http://nodejs.org/api/domain.html

  • 请注意,Domain已被弃用.https://nodejs.org/api/domain.html#domain_domain (6认同)

3rd*_*den 5

签出uncaughtExceptionnode.js中的处理程序.它捕获了冒泡到事件循环的错误.

http://nodejs.org/docs/v0.4.7/api/process.html#event_uncaughtException_

但不抛出错误总是一个更好的解决方案.你可以做一个return res.end('Unabled to load file xxx');

  • 谢谢你的回答,但正如在描述中所写,'uncaughtException`对我没有帮助,因为我无法在那里结束请求,因为我没有'request`或`response`参考.并且你不能完全避免异常(毕竟我喜欢它们并且经常使用它们). (2认同)

chj*_*hjj 5

这是Node现在的问题之一.实际上不可能追踪哪个请求导致在回调中抛出错误.

如果可能的话,您将不得不在回调本身(您仍然具有对请求和响应对象的引用)中处理错误.uncaughtException处理程序将停止退出节点进程,但是首先导致异常的请求将从用户的角度挂起.