Mongoose承诺文件说查询不是承诺?

Eug*_*nic 4 javascript mongoose mongodb node.js promise

来自文档(Mongoose v5.4.1,最新版本):

Mongoose异步操作,如.save()和查询,返回了thenables.这意味着您可以执行MyModel.findOne({})之类的操作.然后()

来自文档的第二个背景说明:

Mongoose查询不是承诺.为方便起见,它们有co和async/await的.then()函数.

什么的Javascript MDN网页状态:

then()方法返回一个Promise.

这是否意味着mongoose对异步函数有另一种实现方式,它们为异步操作的结果保留了then关键字?

换句话说,他们表现得像承诺但不是JS的承诺?

Joh*_*yHK 13

文档:

Mongoose查询不是承诺.它们具有.then()co和async/await的功能,以方便使用.但是,与promises不同,调用查询.then()可以多次执行查询.

因此,与实际承诺不同,如果您then()在查询上多次调用,则实际上会多次执行查询(或更新).

如果您想要实际的承诺,请致电exec()查询.

let promise = Test.findOne({}).exec();
Run Code Online (Sandbox Code Playgroud)

  • 这绝对是**关键的**信息.好一个! (4认同)

T.J*_*der 6

所有的承诺都是thenables,但不是所有的thenables承诺.为了使事情变得更复杂,并非所有的promises都是Promise(由JavaScript的内置Promise构造函数创建的实例).

JavaScript promises是Promises/A +规范的一个实现,它定义了这样的术语:

1.1"promise"是一个对象或函数,其then方法的行为符合此规范.

1.2"thenable"是定义then方法的对象或函数.

所以Mongoose的查询不是承诺,甚至不是那个定义,因为它们的then方法与Promises/A +规范兼容.请参阅JohnnyHK的答案,了解它们与Promises/A +规范不兼容的原因(它们运行查询).

换句话说,他们表现得像承诺但不是JS的承诺?

他们的行为有点像承诺.他们不是承诺.它们then没有按照规范实现,它有副作用(运行查询).如果你想要一个真正的承诺,请参阅JohnnyHK的答案(例如,使用exec).


在一般情况下,如果你有一个thenable这至少在一定程度承诺般,您可以通过使用得到了什么正确的承诺Promise.resolve:

Promise.resolve(theThenable)
.then(/*...*/)
.catch(/*...*/)
.finally(/*...*/);
Run Code Online (Sandbox Code Playgroud)

Promise.resolve将提供一个Promise从属于Mongoose可用/承诺的真实实例.这将适用于Mongoose查询(假设您只执行一次; exec使用Mongoose查询是更好的方法).

  • @JonasWilms - 这取决于.如果Mongoose的`then`返回一个不是'Promise`的Mongoose承诺,而Eugen将它传递给期望真正的'Promise`的东西,那么它可能会有问题.承诺的所有方式都在JavaScript规范中使用,仅依赖于`then`,但这不适用于userland代码...... (3认同)
  • @eugensunic - 所有Mongoose文档承诺提供的是`then`(如果它符合规范,也可以用于`catch`情况).但是如果你想在对象上实际使用`catch`或`finally`,那么就得到一个真正的`Promise`(通过`Promise.resolve(theThenable)`.如果你需要的只是`then`方法,那么你可以直接使用它. (2认同)