猫鼬 - exec函数有什么作用?

时间:2015-07-21 21:22:46

标签: javascript mongoose

我遇到了一段包含查询findOne然后是exec()函数的Mongoose代码。

我以前从未在Javascript中看过那种方法?它到底做了什么?

5 个答案:

答案 0 :(得分:94)

基本上使用mongoose时,可以使用帮助程序检索文档。接受查询条件的每个模型方法都可以通过callbackexec方法执行。

callback

User.findOne({ name: 'daniel' }, function (err, user) {
  //
});

exec

User
  .findOne({ name: 'daniel' })
  .exec(function (err, user) {
      //
  });

因此,当您没有通过回调时,您可以构建查询并最终执行它。

您可以在mongoose docs

中找到更多信息

<强>更新

Promises与Mongoose异步操作结合使用时需要注意的是,Mongoose查询是不是 Promise。查询会返回 thenable ,但如果您需要真实承诺,则应使用exec方法。可以找到更多信息here

在更新期间,我注意到我没有明确回答这个问题:

  

我以前从未在Javascript中看过那种方法?它有什么作用   到底是什么?

它的不是原生JavaScript方法,但是是Mongoose API的一部分。

答案 1 :(得分:27)

丹尼尔非常漂亮地回答了这个问题。要详细说明构建和执行查询的详尽方法列表,请查看以下用例:

查询构建

在调用thenexec之前,Mongoose不会执行查询。这在构建复杂查询时非常有用。一些示例可以包括使用populateaggregate函数。

User.find({name: 'John'}) // Will not execute

通过回调执行

虽然很多人因其嵌套性质而不喜欢,但可以通过提供可选的回调来执行查询。

User.find({name: 'John'}, (err, res) => {}) // Will execute

然后API作为Promises / A +

Mongoose查询确实提供了then功能。这不应与常规承诺相混淆。简单地说,Promises / A +规范要求then函数的工作方式与我们如何习惯承诺一样。

User.find({name: 'John'}).then(); // Will execute
Promise.all([User.find({name: 'John'}), User.find({name: 'Bob'})]) // Will execute all queries in parallel

执行功能

来自Mongoose docs If you need a fully-fledged promise, use the .exec() function.

User.find({name: 'John'}).exec(); // Will execute returning a promise

答案 2 :(得分:6)

如果没有提供回调,

exec()将返回一个承诺。因此,以下模式非常方便和通用 - 它可以很好地处理回调或承诺:

function findAll(query, populate, cb) {

  let q = Response.find(query);

  if (populate && populate.length > 0) {
    q = q.populate(populate);
  }

  // cb is optional, will return promise if cb == null
  return q.lean().exec(cb);

}

我建议在Mongoose上使用Bluebird promises,为此,请使用此调用:

const mongoose = require('mongoose');
mongoose.Promise = require('bluebird');

答案 3 :(得分:1)

所有答案都是正确的,但最简单的方法是使用现代异步等待方法..

async ()=> {
const requiresUser = await User.findByIdAndUpdate(userId,{name:'noname'},{ new:true, 
useFindAndModify: false});

答案 4 :(得分:1)

我从不使用 exec() 函数在模型上完成 CRUD(创建、读取、更新、删除)。当我想在模型上使用 CRUD 时,我会像这样使用它:

const user = await UserModel.findOne(userCondition);

它总是能胜任。所以我想知道“exec() 有什么用”? 当我在猫鼬文档中搜索时,我找到了答案 here

<块引用>

您应该将 exec() 与 await 一起使用吗?

这是故事。
您有两种方法可以对模型执行查询。使用 callback 或使用 exec() 函数。 “但是”您也可以使用 awaitexec() 函数返回一个 promise,您可以将它与 then()async/await 一起使用以在“异步”模型上执行查询。所以问题是“如果我可以只使用 user = await UserModel.find() 并且它可以正常工作,那么我为什么要使用 exec() 函数?”。您可以在 document 中找到的答案是:

awaitexec() 一起使用或不使用它有两个区别。

  • 从功能的角度来看,将 awaitexec() 一起使用或不使用它没有区别。就在您调用没有 exec()callback 的查询时,它返回一个 thenable,它类似于 promise,但它不是 promise。(您可以找到区别 here) .但是当您使用 exec() 运行查询时,您会得到一个 promise 作为响应。
// returns a thenable as response that is not a promise, but you can use await and then() with it.
const user = await UserModel.findOne(userCondition);

// returns exactly a promise.
const user = await UserModel.findOne(userCondition).exec(); 
  • 另一个区别是,如果您将 awaitexec() 一起使用,如果您在执行查询时发现任何错误,您将获得更好的“堆栈跟踪”。所以:

    这两行,做同样的事情:
const user = await UserModel.findOne(userCondition);

// does exactly as the before line does, but you get a better stack trace if any error happened
const user = await UserModel.findOne(userCondition).exec();