猫鼬的诺言文档说查询不是诺言吗?

时间:2018-12-29 15:19:52

标签: javascript node.js mongodb mongoose promise

从文档中获取(猫鼬v5.4.1 ,最新版本):

  

猫鼬异步操作(如.save()和查询)返回   罐头。       这意味着您可以执行MyModel.findOne({})。then()

之类的操作
来自文档的

第二段:

  

猫鼬查询不是承诺。他们有一个.then()函数   和async / await为方便。

Javascript MDN 页面上显示的内容:

  

then()方法返回一个Promise。

这是否意味着猫鼬为异步功能提供了另一种实现方式,即它们为异步操作的结果保留了then关键字?

换句话说,它们像承诺一样,但不是JS承诺吗?

3 个答案:

答案 0 :(得分:9)

来自documentation

  

猫鼬查询不是承诺。它们具有.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