请问 Express 中如何撰写异步 Exception handling?
发布于 9 年前 作者 grass0916 4993 次浏览 最后一次编辑是 8 年前 来自 问答

大家好,我使用 Express 做一 Web app,Express 与 Node 官方对于异步 Exception handling 似乎不太友善,抑或是我没厘清其撰写风格。

不晓得各为前辈能否指点迷津,有关于以下举例情况异步 Error exception。

var express = require('express');
var app     = express();
app.get('/index', function (req, res) {
    ... // 代码,可能会有的错误
    var isUndefined = undefined;
    isUndefined.elements; // undefined.elements 系统要 throw error
});

app.get('/page1', function (req, res) {
    ... // 代码,可能会有的错误
   throw "Error here";
});

以下我理想中的解法,但因为异步callback 这样是行不通的。

try {
    app.get('/index', function (req, res) {
        ... // 代码,可能会有的错误
    });
    app.get('/page1', function (req, res) {
        ... // 代码,可能会有的错误
    });
} catch (e) {
    ... // 处理 Error
}
12 回复

使用bluebird这样的promise库

      Product.findByIdAsync(productId).then(function(product){
        //console.log("spread products= " + products);
        return product.reject(function(err,result){
          // console.dir(result);
          Promise.resolve(result);
        });
        
      }).then(function(result){
        if(result.ok == 1){
          return Product.findByIdAsync(productId);
        }
      }).then(function(product){
        //console.log("spread products= " + products);
        expect(product.status).to.equal(2);
        done()
      }).catch(function(err) {
        done(err);
      });

这里面是对模型做的,在路由里对业务逻辑处理也可以

@i5ting 谢谢前辈您的建议,不过我已经有使用 Async.js 这样的话会因为牴触,需要全部打掉重写。不晓得前辈还有其它的解法吗?

在JavaScript中try…catch是无法捕获异步代码抛出的异常的,node对于异步代码的标准错误处理方式是通过callback的第一个参数传递错误 而Express的设计是通过middleware来统一处理错误,可以看这里:http://expressjs.com/guide/error-handling.html

@grass0916

看一下readme

https://github.com/caolan/async 里面有关于err的回调处理

app.get('/index', function (req, res) {
		try { 
		     ... // 代码,可能会有的错误
		} catch (e) {
		   console.log(e)
		}
});

可以在callback中用try catch,我更推荐这样的写法

app.get('/', listenr);
function listener(req, res) {
	//try catch here
}

@ravenwang @i5ting 谢谢两位前辈,实不相瞒其实我现在就是使用 async callback 的回调机制来处理我「可预期得错误」,但是以下的举例程式码因为设计出现漏洞,如果没有 try catch 做最后一道防线,Node 在执行时就会直接 crash 了(专案目前已上线,希望就算有些小漏洞也不至于系统 crash,写入 log 之后再修正就行)。

我提到自己「可能不可预期的错误」(撰写上的粗心):


app.get('/index', function (req, res) {
	async.waterfall([
		function (callback) {
			if (某种情况为 true 时) {
				callback(null);
			} else {
				callback('Error'); // 这里作 callback error
			}
		},
		function (callback) {
			var objectA = { elementA: 123 };
			callback(null, objectA);
		}
	], function (err, objectA) {
		// 上述的 callback('Error'); 并无传递 objectA
		// 所以亦即 undefined.elementA,这样子 Node 会 Crash!
	    console.log(objectA.elementA); 
	});
});

对于一些可能捕获不到的错误,可以用

process.on('uncaughtException', function(err) {
	//log it
});

来保证node不退出,最好用log4js日志这些未捕获的错误。这是最后一道防线,因为错误是未知的,所以可能造成某个服务不可能用,所以需要谨慎使用

@dayuoba 懒羊羊前辈前述的方法我有想到,目前40 ~ 50 个 app router 看来这可能是唯一解了,前辈后面提到的建议写法获益良多,谢谢你连续几天的帮忙。不晓得对于此类 app 应用,前辈有没有些 design pattern 可供参考长进呢?

@dayuoba 好的,我会看看 uncaughtException 的使用方法!谢谢!

@grass0916 理论方面,中文书籍最好的是<深入浅出nodejs>,可以读一读,我的老外BOSS都知道这本书是中文最好的。 所谓的最佳设计模式,还是需要时间+实践吧。

@dayuoba 好的,我去买本简体书籍学习,听说我们台湾的译本被翻译翻烂了,真可惜。谢谢懒羊羊大大!!

回到顶部