简体   繁体   English

使用node.js进行Javascript异步异常处理

[英]Javascript Asynchronous Exception Handling with node.js

I'm currently working on a node.js app and I'm having the usual asynchronous code issue. 我目前正在研究node.js应用程序,我遇到了常见的异步代码问题。

I'm implementing a service server on top of Node's HTTP module. 我正在Node的HTTP模块上实现一个服务服务器。

This server supports (express like) routes. 此服务器支持(表示类似)路由。 For example I have code that looks like this: 例如,我的代码如下所示:

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

The server needs to be able to withstand failure, I do not want to crash the whole server when there is a problem in a function passed to any. 服务器需要能够承受故障,当传递给任何一个函数时出现问题时,我不想让整个服务器崩溃。 The problem occurs when I'm writing code that looks like: 当我编写的代码如下所示时会出现问题:

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

I don't see how I possible can catch the error here. 我不知道我怎么可能在这里发现错误。 I don't want to crash the server over one server-side glitch, instead I want to serve 500. 我不想让服务器崩溃超过一个服务器端故障,而是我想服务500。

The only solutions I've been able to come up with are really not expressive. 我能够提出的唯一解决方案实际上并不富有表现力。 I've only come up with using process.on("uncaughtException",callback) and similar code using node 0.8 Domains (which is a partial remedy but Domains are currently buggy and this is still not very expressive since I end up having to create a domain for every handle). 我只是想出使用process.on("uncaughtException",callback)和使用节点0.8 Domains类似代码(这是一种部分补救措施但是域名目前是错误的,因为我最终不得不创建每个句柄的域名)。

What I would like to accomplish is binding throw actions from a function to a scope, the ideal solution is something like binding all thrown errors from a function to a specific handler function. 我想要完成的是throw函数从一个函数绑定到一个作用域,理想的解决方案是将所有抛出的错误从一个函数绑定到一个特定的处理函数。

Is this possible? 这可能吗? What is the best practice to handle errors in this case? 在这种情况下处理错误的最佳做法是什么?

I'd like to emphasise that it should be able to continue serving requests after a bad requests, and restarting the server on every request or creating domains for every handler and catching their uncaught exceptions seems like a bad idea to me. 我想强调它应该能够在一个错误的请求后继续提供请求,并在每个请求上重新启动服务器或为每个处理程序创建域并捕获未捕获的异常对我来说似乎是一个坏主意。 Additionally - I've heard promises might be able to assist me (something about throw in promises), can promises aid me in this situation? 另外 - 我听说过承诺可以帮助我(有关throw承诺的事情),在这种情况下可以承诺帮助我吗?

Warning : I would not recommend the original answer using domains, domains are being deprecated in the future, I had a lot of fun writing the original answer but I no longer believe it is too relevant. 警告 :我不推荐使用域名的原始答案,将来不推荐使用域名,我写了原始答案时有很多乐趣,但我不再相信它太相关了。 Instead - I suggest using event emitters and promises that have better error handling - here is the below example with promises instead. 相反 - 我建议使用具有更好错误处理的事件发射器和承诺 - 以下是带有promises的示例。 The promises used here are Bluebird : 这里使用的承诺是蓝鸟

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

With a timeout (note that we have to return the Promise.delay): 超时(注意我们必须返回Promise.delay):

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

With a general NodeJS funciton: 使用一般的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
});

This approach is both fast and catch safe, I recommend it above the below answer which uses domains that are likely not here to stay. 这种方法既快速又安全,我推荐它高于下面的答案,它使用的域名可能不会留下来。


I ended up using domains, I have created the following file I called mistake.js which contains the following code: 我最终使用域名,我创建了以下文件,我称之为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;
    };
};

Here is some example usage: 以下是一些示例用法:

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

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

It also works like normal catch for synchronous code 它也像普通的同步代码捕获一样工作

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

I would appreciate some feedback on the solution 我将很感激对该解决方案的一些反馈

On a side note, in v 0.8 apparently when you catch the exception in the domain it still bubbles to process.on("uncaughtException") . 另外,在v 0.8中,显然当你在域中捕获异常时,它仍然会起泡到process.on("uncaughtException") I dealt with this in my process.on("uncaughtException") with 我在我的process.on("uncaughtException")处理了这个问题

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

However, the documentation suggests against process.on("uncaughtException") any way 但是,文档建议不要以任何方式反对process.on("uncaughtException")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM