一尘不染

使用node.js的Javascript异步异常处理

node.js

我目前正在使用node.js应用程序,并且遇到了通常的异步代码问题。

我正在Node的HTTP模块之上实现服务服务器。

该服务器支持(类似表达)路由。例如,我有如下代码:

server.any("/someRoute",function(req,resp){
    resp.end("this text is sent to clients via http")
});

服务器需要能够承受故障,当传递给任何函数的问题出现时,我不想使整个服务器崩溃。当我编写如下代码时,会发生问题:

server.any("/someRoute",function(req,resp){
    setTimeout(function(){
        throw new Error("This won't get caught");
    },100);
});

我看不到如何在这里捕获错误。我不想因一个服务器端故障而使服务器崩溃,而是要服务500个。

我能够提出的唯一解决方案实际上并没有表现力。我只想出使用process.on("uncaughtException",callback)和使用节点0.8的类似代码的方法Domains(这是部分补救措施,但是Domains当前有问题,并且由于我最终不得不为每个句柄创建一个域,所以它仍然不能很好地表达)。

我想要完成的是将throw动作从功能绑定到作用域,理想的解决方案是将所有抛出的错误从功能绑定到特定的处理函数。

这可能吗?在这种情况下处理错误的最佳实践是什么?

我想强调一点,它应该能够在出现错误请求后继续处理请求,并针对每个请求重新启动服务器或为每个处理程序创建域并捕获未捕获的异常,这对我来说是个坏主意。另外-
我听说诺言可以帮助我(throw诺言中的某些内容),在这种情况下诺言可以帮助我吗?


阅读 222

收藏
2020-07-07

共1个答案

一尘不染

警告
:我不建议使用域的原始答案,以后将不建议使用域,编写原始答案很有趣,但我不再相信它太相关了。相反,我建议使用事件处理程序和具有更好错误处理的Promise,以下是使用Promise的示例。这里使用的承诺是Bluebird

Promise.try(function(){ 
    throw new Error("Something");
}).catch(function(err){
    console.log(err.message); // logs "Something"
});

超时(请注意,我们必须返回Promise.delay):

Promise.try(function() {
    return Promise.delay(1000).then(function(){
        throw new Error("something");
    });
}).catch(function(err){
    console.log("caught "+err.message);
});

使用一般的NodeJS函数:

var fs = Promise.promisifyAll("fs"); // creates readFileAsync that returns promise
fs.readFileAsync("myfile.txt").then(function(content){
    console.log(content.toString()); // logs the file's contents
    // can throw here and it'll catch it
}).catch(function(err){
    console.log(err); // log any error from the `then` or the readFile operation
});

这种方法既快速又安全,我建议在下面的答案上方使用它,因为它使用的域可能不会保留下来。


我最终使用了域,创建了以下文件mistake.js,其中包含以下代码:

var domain=require("domain");
module.exports = function(func){
    var dom = domain.create();
    return { "catch" :function(errHandle){
        var args = arguments;
        dom.on("error",function(err){
            return errHandle(err);
        }).run(function(){
            func.call(null, args);
        });
        return this;
    };
};

这是一些示例用法:

var atry = require("./mistake.js");

atry(function() {
    setTimeout(function(){
        throw "something";
    },1000);
}).catch(function(err){
    console.log("caught "+err);
});

它也像正常捕获同步代码一样工作

atry(function() {
    throw "something";
}).catch(function(err){
    console.log("caught "+err);
});

我希望对解决方案有一些反馈

另外,显然在v
0.8中,当您在域中捕获异常时,它仍然冒泡到process.on("uncaughtException")。我处理这在我process.on("uncaughtException")

 if (typeof e !== "object" || !e["domain_thrown"]) {

但是,文档建议采取process.on("uncaughtException")任何方式

2020-07-07