我正在使用具有新的 async/await 功能的 Node 7.2.1。我也像这样将 Native ES6 Promises 与 mongoose 一起使用 -
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
我的代码流程是这样的-
async function getFollowers(){
try {
const followers = await User.getFollowersFromMongo(req.params.userId);
res.send(followers);
} catch (err) {
winston.error('Printing Error = ', err);
res.status(400).send({success: false, error: err});
}
}
UserSchema.statics.getFollowersFromMongo = async(userId) => {
try {
let aggregateQuery = []; //some syntactical error in mongo query to produce exception
const followers = await User.aggregate(aggregateQuery);
return followers.map(follower => follower.followerData);
}
catch (err) {
return Promise.reject(err);
}
};
这段代码绝对没问题。当产生一些错误时就会出现问题。所以我特意修改了我的 mongoose 查询,以便 MongoDB 会抛出错误。
现在 MongoDB,正如预期的那样抛出一个错误,我的代码完全捕获了这个错误,并返回给客户端一个 400 错误代码。
问题是,即使错误(故意的)已被我发现,Node.js 仍然给我这个警告 -
error: Printing Error = MongoError: path option to $unwind stage should be prefixed with a '$': followerData
at Function.MongoError.create (/home/node_modules/mongodb-core/lib/error.js:31:11)
at /home/node_modules/mongodb-core/lib/connection/pool.js:483:72
at authenticateStragglers (/home/node_modules/mongodb-core/lib/connection/pool.js:429:16)
at Connection.messageHandler (/home/node_modules/mongodb-core/lib/connection/pool.js:463:5)
at Socket.<anonymous> (/home/node_modules/mongodb-core/lib/connection/connection.js:317:22)
at emitOne (events.js:96:13)
at Socket.emit (events.js:188:7)
at readableAddChunk (_stream_readable.js:176:18)
at Socket.Readable.push (_stream_readable.js:134:10)
at TCP.onread (net.js:551:20)
GET /user/385/followers 400 39.868 ms - 263
(node:10158) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): MongoError: path option to $unwind stage should be prefixed with a '$': followerData
(node:10158) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
可以看出,我的请求已返回 400 状态,并且我的错误日志也已从初始方法的 catch block 中打印出来,但 Node.js 仍然说错误消息未处理.
为什么即使发现了同样的错误,它仍然这么说?
更新- 感谢@dvlsg 和@Bergi,该错误已在 4.7.5 版本中修复
最佳答案
mongoose aggregate 如何与 async/await 一起玩,肯定有一些奇怪的地方。对我来说似乎是一个错误。如果是,绝对应该报告给 mongoose。
值得庆幸的是,有一个简单的解决方法:
const followers = await User.aggregate(aggregateQuery).exec();
添加显式 .exec()
允许我按预期捕获聚合管道错误。
我认为增加这里困惑的潜在问题是有一个额外的 Promise
被拒绝并且没有被处理。因为从技术上讲,您是在这里正确处理预期的拒绝。否则您将看不到 Printing error = ...
被记录。
这是我认为正在发生的事情 --
- 您
等待 User.aggregate()
Aggregate#then()
通过await
与thenables
一起调用(我认为)Aggregate#exec()
由Aggregate#then()
内部调用- 请注意 a callback is provided到
exec()
- 请注意 a callback is provided到
Aggregate#exec()
中的新Promise
是created , 和 will be rejected- This 是未处理的
Promise
,我相信。
- This 是未处理的
- 由于从
Aggregate#then()
向Aggregate#exec()
提供了回调,Aggregate# 中的
将是 provided to the callbackError
exec() - 在
Aggregate#then()
的回调中,一个新的 createdPromise
被拒绝- 我相信这个
Promise
是按预期处理的,因为它是Aggregate#then()
的返回值
- 我相信这个
我想我可以通过注释掉 this line 来证实我的怀疑在 mongoose Aggregate
定义中。这将防止未处理的拒绝处理程序被命中。顺便说一下,我并不是建议这样做。这只是额外的证据,而不是解决方案,因为现在我只有一个未被拒绝的 Promise
浮现。
这是一种在自包含代码中重现未捕获拒绝的最小方法,与 node --harmony-async-await
一起运行(在 Node v7 上测试.2.1
)
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost/temp');
const userSchema = new mongoose.Schema({
name: 'string'
});
const User = mongoose.model('User', userSchema);
async function run() {
try {
await User.aggregate([]);
}
catch (err) {
console.log('caught expected error:', err);
}
}
run();
关于javascript - Node.js UnhandledPromiseRejectionWarning 即使在捕获它之后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41247012/