Promises
内置 Promises
Mongoose 的异步操作,例如 .save()
和查询,返回 thenables。这意味着您可以像这样使用 MyModel.findOne({}).then()
和 await MyModel.findOne({}).exec()
(如果您正在使用 async/await)。
您可以在 api 文档中 找到特定操作的返回类型。您还可以阅读更多关于 Mongoose 中的 promises 的内容。
const gnr = new Band({
name: 'Guns N\' Roses',
members: ['Axl', 'Slash']
});
const promise = gnr.save();
assert.ok(promise instanceof Promise);
promise.then(function(doc) {
assert.equal(doc.name, 'Guns N\' Roses');
});
查询不是 promises
Mongoose 查询 不是 promises。它们有一个 .then()
函数,方便使用 co 和 async/await。如果您需要一个完整的 promise,请使用 .exec()
函数。
const query = Band.findOne({ name: 'Guns N\' Roses' });
assert.ok(!(query instanceof Promise));
// A query is not a fully-fledged promise, but it does have a `.then()`.
query.then(function(doc) {
// use doc
});
// `.exec()` gives you a fully-fledged promise
const promise = Band.findOne({ name: 'Guns N\' Roses' }).exec();
assert.ok(promise instanceof Promise);
promise.then(function(doc) {
// use doc
});
查询是 thenable
尽管查询不是 promises,但查询是 thenables。这意味着它们有一个 .then()
函数,因此您可以使用 promise 链或 async await 将查询用作 promises。
Band.findOne({ name: 'Guns N\' Roses' }).then(function(doc) {
// use doc
});
您应该在 await
中使用 exec()
吗?
使用 await
与查询有两种选择
await Band.findOne();
await Band.findOne().exec();
从功能上来说,这两种方法是等效的。但是,我们建议使用 .exec()
,因为它可以提供更好的堆栈跟踪。
const doc = await Band.findOne({ name: 'Guns N\' Roses' }); // works
const badId = 'this is not a valid id';
try {
await Band.findOne({ _id: badId });
} catch (err) {
// Without `exec()`, the stack trace does **not** include the
// calling code. Below is the stack trace:
//
// CastError: Cast to ObjectId failed for value "this is not a valid id" at path "_id" for model "band-promises"
// at new CastError (/app/node_modules/mongoose/lib/error/cast.js:29:11)
// at model.Query.exec (/app/node_modules/mongoose/lib/query.js:4331:21)
// at model.Query.Query.then (/app/node_modules/mongoose/lib/query.js:4423:15)
// at process._tickCallback (internal/process/next_tick.js:68:7)
err.stack;
}
try {
await Band.findOne({ _id: badId }).exec();
} catch (err) {
// With `exec()`, the stack trace includes where in your code you
// called `exec()`. Below is the stack trace:
//
// CastError: Cast to ObjectId failed for value "this is not a valid id" at path "_id" for model "band-promises"
// at new CastError (/app/node_modules/mongoose/lib/error/cast.js:29:11)
// at model.Query.exec (/app/node_modules/mongoose/lib/query.js:4331:21)
// at Context.<anonymous> (/app/test/index.test.js:138:42)
// at process._tickCallback (internal/process/next_tick.js:68:7)
err.stack;
}
想要学习如何在没有谷歌和 Stack Overflow 上相互矛盾的答案的情况下检查您最喜欢的 npm 模块是否与 async/await 兼容吗?掌握 Async/Await 的第 4 章解释了确定 React 和 Mongoose 等框架是否支持 async/await 的基本原则。 获取您的副本!