Node.js 未捕获从mongoose promise回调函数引发的错误
我花了太多时间试图弄清楚为什么我的express.js控制器没有响应一个简单的查询,并且弄清楚了从Mongoose promise回调引发的运行时错误正在悄悄地中断回调过程 以下是我的代码的简化版本:Node.js 未捕获从mongoose promise回调函数引发的错误,node.js,express,error-handling,mongoose,promise,Node.js,Express,Error Handling,Mongoose,Promise,我花了太多时间试图弄清楚为什么我的express.js控制器没有响应一个简单的查询,并且弄清楚了从Mongoose promise回调引发的运行时错误正在悄悄地中断回调过程 以下是我的代码的简化版本: server.get('/api/test', function (req, res, next) { User.find({}).exec().then(function success(users){ console.log('SUCCESS'); typo[0] =
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
显示在我的控制台中,但随后什么也没有发生。没有响应给用户,由我的输入错误引起的错误没有出现在我的控制台中,错误回调也没有被调用
我知道不应该从回调函数中抛出异常,但在这种情况下,这只是一个输入错误,每当出现此类错误时,我都会收到警告(例如,标准输出中的堆栈跟踪)。(毕竟,我们是人类……)
在您看来,在promise回调中出现此类错误时,获得反馈的最佳方式是什么?theexec()
有两个承诺
.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
});
});
});
这是Mongoose使用坏承诺实现的错误。承诺是安全的,因此异常会被捕获(以便以后可以由未来的代码处理)——未来的代码永远不会出现,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
});
这具有比猫鼬承诺更快的优势,因此不会造成性能损失。或者,如果您非常保守,不想获得bluebird的性能和API收益,您可以使用原生承诺:
// Promise is the native promise
Promise.resolve(User.find({}).exec()).then(function(data){
JSON.prase("dsa");
});
然后,假设您运行的是现代版本的nodejs(读:io.jsv1.4.1或更高版本),您可以订阅承诺拒绝:
process.on("unhandledRejection", function(p, why){
console.log("FOUND ERROR!!!!", p , why);
});
因此,异常不会被默默地抑制 不,它不工作。=><代码>类型错误:对象#没有方法“catch”对不起,我更新了我的答案,在promise的调用类型中,mongoose和sequelize之间存在冲突。我相信
exec()。catch(handler)
类似于exec()。然后(null,handler)
在承诺的一般情况下。。。。使用两个then()
相当于将成功和错误回调组合到同一个then()
。cf=>它不能解决问题。区别在于。然后是(handler)。然后是(null,handler)
和。然后是(handler,handler2)
这就是我将“投掷安全”称为“投掷危险”的原因。错误被承诺代码捕获,并被“吞没”。幸运的是,错误也在传播。要使其可见,请尝试在承诺链的末尾添加一个.catch()
,并记录错误。感谢您的精彩回复,Benjamin!太糟糕了,显然没有办法使用另一个Promise实现而不进行替换(例如,findAsync()
而不是find()
)或包装(Promise.resolve()
)我所有的Mongoose DB调用…@adrienjoly,如果这能让你感觉更好,我也在问题追踪器上问过:)如果你想帮助打开一个问题,要求他们实现拒绝挂钩(这是一个规范),也许他们会知道这对我不起作用,直到我添加了以下内容:Mongoose.set('error',true)
。我的代码略有不同,我使用的是Promise=require(“蓝鸟”)
mongoose=require('mongoose')
mongoose.Promise=Promise
与promisifyAll(require(“mongoose”))有区别吗