Promise
内置 Promise
¥Built-in Promises
Mongoose 异步操作(例如 .save()
和查询)返回 thenables。这意味着如果你使用 async/await,则可以执行 MyModel.findOne({}).then()
和 await MyModel.findOne({}).exec()
之类的操作。
¥Mongoose async operations, like .save()
and queries, return thenables.
This means that you can do things like MyModel.findOne({}).then()
and
await MyModel.findOne({}).exec()
if you're using
async/await.
你可以找到具体操作的返回类型 在 API 文档中 ,也可以阅读有关 Mongoose 中的 promise 的更多信息。
¥You can find the return type of specific operations in the api docs You can also read more about promises in Mongoose.
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');
});
查询不是 promise
¥Queries are not promises
Mongoose 查询 不是 promise。为了方便起见,它们有 .then()
函数用于 co 和 async/await。如果你需要完整的 promise,请使用 .exec()
函数。
¥Mongoose queries are not promises. They have a .then()
function for co and async/await as
a convenience. If you need
a fully-fledged promise, use the .exec()
function.
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
});
可以进行查询
¥Queries are thenable
虽然查询不是 promise,但查询是 thenables。这意味着它们有 .then()
函数,因此你可以将查询用作带有 Promise 链或 异步等待 的 Promise
¥Although queries are not promises, queries are thenables.
That means they have a .then()
function, so you can use queries as promises with either
promise chaining or async await
Band.findOne({ name: 'Guns N\' Roses' }).then(function(doc) {
// use doc
});
你应该将 exec()
与 await
一起使用吗?
¥Should You Use exec()
With await
?
使用 await
进行查询有两种选择:
¥There are two alternatives for using await
with queries:
await Band.findOne();
await Band.findOne().exec();
就功能而言,这两者是等效的。但是,我们建议使用 .exec()
,因为这可以为你提供更好的堆栈跟踪。
¥As far as functionality is concerned, these two are equivalent.
However, we recommend using .exec()
because that gives you
better stack traces.
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;
}
Want to learn how to check whether your favorite npm modules work with
async/await without cobbling together contradictory answers from Google
and Stack Overflow? Chapter 4 of Mastering Async/Await explains the
basic principles for determining whether frameworks like React and
Mongoose support async/await.
Get your copy!
