mongoose在async函数用不用使用exec方法

1、现象

var schema = new mongoose.Schema({ name: 'string', size: 'string' });
var tankModel = mongoose.model('tank', schema);

mongoose查找方法

async function findByName(name) {
  let nameDoc = await tankModel.findOne({name: name});
  let nameDocT = await tankModel.findOne({name: name}).exec();

  console.log('nameDoc: ', nameDoc);
  console.log('nameDocT: ', nameDocT);
}
findByName('jack');

上边方法中,最后带exec和不带exec都可以得到doc结果,这是为什么呢,我们先来看下是什么

async function findByName(name) {
  let nameDoc = tankModel.findOne({name: name});
  let nameDocT = tankModel.findOne({name: name}).exec();

  console.log('nameDoc: ', nameDoc instanceof Promise); //结果为false
  console.log('nameDocT: ', nameDocT instanceof Promise); //结果为true
}
findByName('jack');

我们看到执行exec后,返回的是Promise对象,而不执行exec则不是。

2、原因

findOne.png

我们查看mongoose文档,findOne方法返回的是Query对象。Query的exec方法返回的是Promise对象

exec.png
那么Query既然不是Promise对象,为什么会在async函数的await命令后执行呢?我们先看看哪些可以在await后边(参考阮一峰老师的ES6入门)
await后边可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象),还可以是一个thenable对象(即定义then方法的对象),这时await会将其等同于 Promise 对象。

function print() {}
print.prototype.then = function (resolve, reject) {
  setTimeout(function () {
    console.log('start....');
    resolve('ddd');
  }, 1000)
};

async function main() {
  await new print();
  console.log('time end...')
}
main().catch(err => console.log('err--->', err));

执行结果为:

start....
time end...

那我们来看看Query是否也是一个thenable对象呢(Query的then方法)

then.png
我们看到,Query确实是一个thenable对象,同时它执行完之后会返回一个真正的Promise对象。

3、结论

我们可知,在async函数await后边查找结果,带不带exec都可以,只不过一个返回的是真正的Promise对象,一个是伪Promise对象。

你可能感兴趣的:(mongoose在async函数用不用使用exec方法)