从文档中获取(猫鼬v5.4.1 ,最新版本):
来自文档的猫鼬异步操作(如.save()和查询)返回 罐头。 这意味着您可以执行MyModel.findOne({})。then()
之类的操作
第二段:
猫鼬查询不是承诺。他们有一个.then()函数 和async / await为方便。
Javascript MDN 页面上显示的内容:
then()方法返回一个Promise。
这是否意味着猫鼬为异步功能提供了另一种实现方式,即它们为异步操作的结果保留了then关键字?
换句话说,它们像承诺一样,但不是JS承诺吗?
答案 0 :(得分:9)
猫鼬查询不是承诺。它们具有
.then()
函数 和async / await为方便。但是,与承诺不同的是, 查询的.then()
可以多次执行查询。
因此,与实际的承诺不同,如果您多次查询then()
,那么实际上您会多次执行查询(或更新)。
如果您需要实际的承诺,请在查询中致电exec()
。
let promise = Test.findOne({}).exec();
答案 1 :(得分:5)
所有 promise 是 thenables ,但并非所有 thenables 都是 promises 。为了使事情变得更复杂,并非所有 promise 都是Promise
(由JavaScript的内置Promise
构造函数创建的实例)。
JavaScript承诺是Promises/A+ specification的实现,它定义了以下术语:
1.1“承诺”是具有
then
方法的对象或函数,其行为符合此规范。1.2“ thenable”是定义
then
方法的对象或函数。
所以Mongoose的查询不是不是承诺,甚至没有这个定义,因为它们的then
方法与Promises / A +规范不兼容。有关它们为何与Promises / A +规范不兼容(请运行查询)的信息,请参见JohnnyHK's answer。
换句话说,它们像承诺一样,但不是JS承诺吗?
他们的行为有点像诺言。他们不是承诺。它们的then
尚未按规范实现,它具有副作用(运行查询)。如果您想要一个真实的承诺,请参阅JohnnyHK's answer(例如,使用exec
)。
通常,如果您的 thenable 至少有点像诺言,则可以使用Promise.resolve
来获得适当的诺言:
Promise.resolve(theThenable)
.then(/*...*/)
.catch(/*...*/)
.finally(/*...*/);
Promise.resolve
将提供一个真实的Promise
实例,该实例从属于Mongoose thenable / promise。这将适用于Mongoose查询(前提是您只需执行一次; exec
是使用Mongoose查询的更好方法)。
答案 2 :(得分:1)
它们像“承诺一样”,这意味着您可以await
并对其调用.then()
和.catch()
,但是它们不是instanceof Promise
。