使用 node.js 进行 Javascript 异步异常处理 [英] Javascript Asynchronous Exception Handling with node.js
问题描述
我目前正在开发一个 node.js 应用程序,但遇到了常见的异步代码问题.
I'm currently working on a node.js app and I'm having the usual asynchronous code issue.
我正在 Node 的 HTTP 模块之上实现一个服务服务器.
I'm implementing a service server on top of Node's HTTP module.
这个服务器支持(express like)路由.例如,我的代码如下所示:
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")
});
服务器需要能够承受故障,当传递给any的函数出现问题时,我不想让整个服务器崩溃.当我编写如下代码时会出现问题:
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);
});
我不知道如何在此处捕获错误.我不想因为一个服务器端故障而使服务器崩溃,而是希望提供 500 个服务.
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.
我能想出的唯一解决方案真的没有表现力.我只是想出了使用 process.on("uncaughtException",callback)
和使用节点 0.8 Domains
的类似代码(这是一种部分补救措施,但域目前有问题这仍然不是很有表现力,因为我最终不得不为每个句柄创建一个域).
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).
我想要完成的是将 throw
操作从函数绑定到作用域,理想的解决方案是将所有抛出的错误从函数绑定到特定的处理函数.
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.
这可能吗?在这种情况下处理错误的最佳做法是什么?
Is this possible? What is the best practice to handle errors in this case?
我想强调的是,它应该能够在出现错误请求后继续服务请求,并且在每个请求上重新启动服务器或为每个处理程序创建域并捕获它们未捕获的异常对我来说似乎是一个坏主意.此外 - 我听说 Promise 可能会帮助我(关于 throw
in Promise),在这种情况下,Promise 可以帮助我吗?
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?
推荐答案
警告:我不推荐使用域的原始答案,域在未来将被弃用,我玩得很开心写原始答案,但我不再认为它太相关了.相反 - 我建议使用具有更好错误处理能力的事件发射器和承诺 - 这是下面的例子,而不是承诺.这里使用的承诺是 Bluebird:
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. The promises used here are Bluebird:
Promise.try(function(){
throw new Error("Something");
}).catch(function(err){
console.log(err.message); // logs "Something"
});
超时(注意我们必须返回 Promise.delay):
With a timeout (note that we have to return the Promise.delay):
Promise.try(function() {
return Promise.delay(1000).then(function(){
throw new Error("something");
});
}).catch(function(err){
console.log("caught "+err.message);
});
使用通用的 NodeJS 函数:
With a general NodeJS funciton:
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.
我最终使用了域,我创建了以下名为 mistake.js
的文件,其中包含以下代码:
I ended up using domains, I have created the following file I called mistake.js
which contains the following code:
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);
});
它也像同步代码的普通捕获一样工作
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
附带说明,在 v 0.8 中,显然当您捕获域中的异常时,它仍然冒泡到 process.on("uncaughtException")
.我在我的 process.on("uncaughtException")
中用
On a side note, in v 0.8 apparently when you catch the exception in the domain it still bubbles to process.on("uncaughtException")
. I dealt with this in my process.on("uncaughtException")
with
if (typeof e !== "object" || !e["domain_thrown"]) {
然而,文档建议以任何方式反对 process.on("uncaughtException")
However, the documentation suggests against process.on("uncaughtException")
any way
这篇关于使用 node.js 进行 Javascript 异步异常处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!