猫鼬承诺文档说查询不是承诺?
Posted
技术标签:
【中文标题】猫鼬承诺文档说查询不是承诺?【英文标题】:Mongoose promises documentation says queries are not promises? 【发布时间】:2019-05-27 00:03:26 【问题描述】:来自文档(Mongoose v5.4.1,最新版本):
Mongoose 异步操作,如 .save() 和查询,返回 那时的事。 这意味着您可以执行 MyModel.findOne().then() 之类的操作
文档中的第二段说明:
Mongoose 查询不是承诺。他们有一个用于 co 的 .then() 函数 和 async/await 方便。
Javascript MDN 网页说明了什么:
then() 方法返回一个 Promise。
这是否意味着 mongoose 有另一种异步函数的实现,他们为异步操作的结果保留 then 关键字?
换句话说,它们的行为类似于 Promise,但不是 JS Promise?
【问题讨论】:
【参考方案1】:来自documentation:
Mongoose 查询不是承诺。他们有一个
.then()
函数 和 async/await 作为一种方便。然而,与 promises 不同的是,调用 查询的.then()
可以多次执行查询。
因此,与实际的承诺不同,如果您在查询中多次调用 then()
,您实际上是多次执行查询(或更新)。
如果您想要一个实际的承诺,请在查询中调用exec()
。
let promise = Test.findOne().exec();
【讨论】:
【参考方案2】:所有 promises 都是 thenables,但并非所有 thenables 都是 promises。更复杂的是,并非所有 promises 都是 Promise
s(由 javascript 的内置 Promise
构造函数创建的实例)。
JavaScript 承诺是 Promises/A+ specification 的一个实现,它定义了这样的术语:
1.1 “promise”是具有
then
方法的对象或函数,其行为符合本规范。1.2 “thenable”是定义
then
方法的对象或函数。
所以 Mongoose 的查询不是承诺,即使按照这个定义也不行,因为他们的 then
方法不与 Promises/A+ 规范兼容。请参阅JohnnyHK's answer,了解它们与 Promises/A+ 规范不兼容的原因(它们运行查询)。
换句话说,它们的行为类似于 Promise,但不是 JS Promise?
他们只是有点像承诺。它们不是承诺。他们的then
没有按照规范实现,它有副作用(运行查询)。如果你想要一个真正的承诺,请参阅JohnnyHK's answer(例如,使用exec
)。
一般来说,如果你有一个至少有点类似于 Promise 的 thenable,你可以通过使用 Promise.resolve
得到一个适当的 Promise:
Promise.resolve(theThenable)
.then(/*...*/)
.catch(/*...*/)
.finally(/*...*/);
Promise.resolve
将提供一个真正的Promise
实例,解析 Mongoose thenable/promise:它将等待 thenable/promise 解决,然后以相同的方式解决。这适用于 Mongoose 查询(前提是您只执行一次;exec
是 Mongoose 查询的更好方法)。
【讨论】:
我明白了。换句话说,如果我不将其打包在 Promise 中,那么 then() 之后的 catch() 将毫无意义? @eugen 如果是“承诺”,.then()
必须返回“承诺”,您可以将其用作Promise
,不会有任何区别。
@eugensunic - 所有 Mongoose 文档都承诺提供 then
(如果符合规范,也可用于 catch
情况)。但是,如果您想在对象上实际使用catch
或finally
,请改为获取真正的Promise
(通过Promise.resolve(theThenable)
。如果您只需要then
方法,那么您可以直接使用它。
@JonasWilms - 这取决于。如果 Mongoose 的 then
返回一个不是 Promise
的 Mongoose 承诺,并且 Eugen 将其传递给期待真正的 Promise
的东西,这可能是有问题的。所有在 JavaScript 规范中使用 Promise 的方式都只依赖于then
,但这并不适用于用户空间代码......【参考方案3】:
它们是“promise like”,这意味着您可以await
他们并在他们身上调用.then()
和.catch()
,但他们不是instanceof Promise
。
【讨论】:
以上是关于猫鼬承诺文档说查询不是承诺?的主要内容,如果未能解决你的问题,请参考以下文章