我花了太多时间试图弄清楚为什么我的express.js控制器没有响应一个简单的查询,并发现从Mongoose-promise回调中发出的运行时错误正在默默地中断回调过程。
以下是我的代码的简化版本:
server.get('/api/test', function (req, res, next) {
User.find({}).exec().then(function success(users){
console.log('SUCCESS');
typo[0] = 1; // throws a runtime error
res.json(users);
}, function error(err){
console.log('ERROR');
res.json({error: err});
});
});
这导致SUCCESS
出现在我的控制台中,但没有任何反应。没有给用户做出响应,我的拼写错误导致的错误没有出现在我的控制台中,并且也没有调用错误回调。
我知道不应该从回调函数中抛出异常,但在这种情况下,这只是一个错字,每当一个人被警告(例如我的标准输出中的堆栈跟踪)是有意义的犯了这种错误。 (毕竟,我们是人类......)
在您看来,在承诺回调中出现此类错误时,获得反馈的最佳方法是什么?
答案 0 :(得分:7)
这是Mongoose使用不良承诺实施的错误。 Promise是安全的,所以异常被捕获(因此它们可以在以后的代码中处理) - 未来的代码永远不会出现,而Mongoose从未报告它没有。良好的承诺实施不会受此问题的影响。
您的选择是两个:
使用像Bluebird这样的库:
var Promise = require("bluebird");
var mongoose = Promise.promisifyAll(require("mongoose"));
User.findAsync({}).then(function(data){
JSON.prase("dsa"); // not a silent failure, will show up, easy debugging
});
这具有比猫鼬承诺更快的优点,因此没有性能损失。或者,如果您非常保守并且不想要蓝鸟的性能和API增益 - 您可以使用原生承诺:
// Promise is the native promise
Promise.resolve(User.find({}).exec()).then(function(data){
JSON.prase("dsa");
});
然后,假设您正在运行nodejs的现代变体(读取:io.js v 1.4.1或更高版本),您可以订阅承诺拒绝:
process.on("unhandledRejection", function(p, why){
console.log("FOUND ERROR!!!!", p , why);
});
所以异常不会被默默地压制。
答案 1 :(得分:3)
exec()
有两个承诺
.then(function)
.then(null , function)
试试这个,我认为这会有所帮助
server.get('/api/test', function(req, res, next) {
User.find({}).exec()
.then(function success(users) {
console.log('SUCCESS');
typo[0] = 1; // throws a runtime error
res.json(users);
})
.then(null, function error(err) {
console.log('ERROR');
res.json({
error: err
});
});
});