Mangosta - ¿Qué hace la función ejecutiva?

100

Encontré un fragmento de código de Mongoose que incluía una consulta findOne y luego una función exec ().

¿Nunca había visto ese método en Javascript antes? ¿Qué hace exactamente?

user439133
fuente

Respuestas:

144

Básicamente, cuando se usa mangosta, los documentos se pueden recuperar usando ayudantes. Cada método de modelo que acepta condiciones de consulta se puede ejecutar mediante un método callbacko exec.

callback:

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

exec:

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

Por lo tanto, cuando no pasa una devolución de llamada, puede crear una consulta y finalmente ejecutarla.

Puede encontrar información adicional en los documentos de mangosta .

ACTUALIZAR

Algo a tener en cuenta al usar Promesas en combinación con operaciones asíncronas de Mongoose es que las consultas de Mongoose no son Promesas. Las consultas devuelven un thenable , pero si necesita una Promesa real , debe usar el execmétodo. Puede encontrar más información aquí .

Durante la actualización, noté que no respondí explícitamente a la pregunta:

¿Nunca había visto ese método en Javascript antes? ¿Qué hace exactamente?

Bueno, no es un método JavaScript nativo, sino parte de la API de Mongoose.

danillouz
fuente
4
¿Qué pasa si configuré mongoose.Promise = require ('bluebird'), todavía necesito usar .exec ()? Gracias.
wayofthefuture
4
@wayofthefuture encuentro los documentos realmente confuso sobre este asunto, pero creo que todavía tienen que llamar al execmétodo. Esto es lo que hacen al menos en los documentos. Para estar seguro, puede comprobarlo usted mismo Model.find() instanceof require('bluebird'). Espero que esto ayude.
danillouz
1
Y luego está la cuestión de otras operaciones como delete e insertMany ... ¿sería necesario exec () en estos casos? Eliminar tendría que usar algún tipo de consulta debajo del capó ...
wayofthefuture
1
Exec también devuelve una promesa, si no se pasa de devolución de llamada, que es muy conveniente debo decir
Alexander Mills
Podría salvar a alguien . Si cree que Model.update () hará su trabajo y no espere a que algunos datos no tan importantes se actualicen y devuelvan una respuesta a la API; Tu actualización no se ejecutará. Necesita Model.update().exec()asegurarse de que se ejecutará. Luego, puede responder a la API sin esperar la actualización.
Yogesh
48

Daniel ha respondido a esto muy bien. Para elaborar una lista exhaustiva de formas de crear y ejecutar consultas, observe los siguientes casos de uso:

Construcción de consultas

Mangosta no se ejecutará hasta que una consulta theno execha sido llamado sobre ella. Esto es muy útil cuando se crean consultas complejas. Algunos ejemplos pueden incluir el uso de las funciones populatey aggregate.

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

Ejecución mediante devolución de llamada

Aunque a muchos no les gusta debido a su naturaleza anidada, las consultas se pueden ejecutar proporcionando la devolución de llamada opcional.

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

Luego API como Promesas / A +

Las consultas de Mongoose proporcionan una thenfunción. Esto no debe confundirse con promesas regulares. En pocas palabras, la especificación Promises / A + requiere que una thenfunción funcione de manera muy similar a como estamos acostumbrados con las promesas.

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

La función ejecutiva

De los documentos de Mongoose If you need a fully-fledged promise, use the .exec() function.

User.find({name: 'John'}).exec(); // Will execute returning a promise
Anshul Koka
fuente
1
los documentos no lo mencionaron explícitamente, pero los ejemplos muestran que User.save () también devuelve una promesa. Aparte de exec () y save (), ¿algún otro método de mangosta en el modelo devuelve una promesa, o son solo estos dos?
thetrystero
Como se señaló anteriormente, también puede usar thenen una consulta para devolver una promesa. Esto no es muy diferente a exec. El caso de uso que encuentro útil es cuando se usa algo como Promise.all. Sin execembargo, no estoy seguro de si la promesa devuelta por funciona en tales contextos.
Anshul Koka
[RESPUESTA ACEPTADA]
Cody
¿Puede agregar un ejemplo completo con .exec ()? @AnshulKoka ¿Es que .exec () automáticamente hace que la consulta sea asincrónica o debo agregar async /
await?
Hacer que la consulta sea asincrónica requerirá async / await, por lo que no estoy seguro de entender la pregunta. Solo espere el prefijo de mi ejemplo para su solicitud de un ejemplo completo.
Anshul Koka
7

exec()devolverá una promesa si no se proporciona ninguna devolución de llamada. Entonces, el siguiente patrón es muy conveniente y genérico: puede manejar devoluciones de llamada o promesas muy bien:

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);

}

Recomiendo usar las promesas de Bluebird con Mongoose, para hacer eso, use esta llamada:

const mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
Alexander Mills
fuente
¿Por qué necesitamos bluebird? cuando tenemos exec ()
Indraraj26