Mongoose - Que fait la fonction exec?

101

Je suis tombé sur un morceau de code Mongoose qui comprenait une requête findOne puis une fonction exec ().

Je n'ai jamais vu cette méthode en Javascript avant? Que fait-il exactement?

user439133
la source

Réponses:

146

Fondamentalement, lorsque vous utilisez la mangouste, les documents peuvent être récupérés à l'aide des helpers. Chaque méthode de modèle qui accepte les conditions de requête peut être exécutée au moyen de a callbackou de la execméthode.

callback:

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

exec:

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

Par conséquent, lorsque vous ne transmettez pas de rappel, vous pouvez créer une requête et éventuellement l'exécuter.

Vous pouvez trouver des informations supplémentaires dans la documentation sur la mangouste .

METTRE À JOUR

Quelque chose à noter lors de l'utilisation de Promises en combinaison avec des opérations asynchrones Mongoose est que les requêtes Mongoose ne sont pas des promesses. Les requêtes renvoient un alorsable , mais si vous avez besoin d'une vraie promesse, vous devez utiliser la execméthode. Plus d'informations peuvent être trouvées ici .

Lors de la mise à jour, j'ai remarqué que je n'avais pas répondu explicitement à la question:

Je n'ai jamais vu cette méthode en Javascript avant? Que fait-il exactement?

Ce n'est pas une méthode JavaScript native, mais une partie de l'API Mongoose.

Danillouz
la source
4
Et si j'ai défini mongoose.Promise = require ('bluebird'), dois-je encore utiliser .exec ()? Merci.
wayofthefuture
4
@wayofthefuture Je trouve la documentation vraiment déroutante à ce sujet, mais je pense que vous devez toujours appeler la execméthode. C'est au moins ce qu'ils font dans la documentation. Pour être sûr de pouvoir vérifier vous-même avec Model.find() instanceof require('bluebird'). J'espère que cela t'aides.
danillouz
1
Et puis il y a la question des autres opérations telles que delete et insertMany ... est-ce que exec () serait nécessaire dans ces cas? Supprimer devrait utiliser une sorte de requête sous le capot ...
wayofthefuture
1
exec renvoie également une promesse, si aucun rappel n'est passé, ce qui est très pratique je dois dire
Alexander Mills
Cela pourrait sauver quelqu'un . Si vous pensez que Model.update () fera son travail et n'attendez pas que certaines données pas si importantes soient mises à jour et renvoyer la réponse à l'API; Votre mise à jour ne s'exécutera pas. Vous devez Model.update().exec()vous assurer qu'il s'exécutera. Ensuite, vous pouvez répondre à l'API sans attendre la mise à jour.
Yogesh
49

Daniel a très bien répondu à cela. Pour élaborer une liste exhaustive des moyens de créer et d'exécuter des requêtes, examinez les cas d'utilisation suivants:

Création de requêtes

Mangouste n'exécutera une requête jusqu'à ce que thenou execa été fait appel à elle. Ceci est très utile lors de la création de requêtes complexes. Certains exemples peuvent inclure l'utilisation des fonctions populateet aggregate.

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

Exécution par rappel

Bien que beaucoup n'aiment pas en raison de sa nature d'imbrication, les requêtes peuvent être exécutées en fournissant le rappel facultatif.

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

Puis l'API comme promesses / A +

Les requêtes Mongoose fournissent une thenfonction. Cela ne doit pas être confondu avec des promesses régulières. En termes simples, la spécification Promises / A + nécessite une thenfonction pour fonctionner de la même manière que nous sommes habitués aux promesses.

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

La fonction exec

Tiré de la documentation Mongoose If you need a fully-fledged promise, use the .exec() function.

User.find({name: 'John'}).exec(); // Will execute returning a promise
Anshul Koka
la source
1
la documentation ne l'a pas mentionné explicitement mais les exemples montrent que User.save () renvoie également une promesse. En dehors de exec () et save (), toutes les autres méthodes mangouste du modèle renvoient-elles une promesse, ou est-ce juste ces deux-là?
thetrystero
Comme indiqué ci-dessus, vous pouvez également utiliser thenune requête pour renvoyer une promesse. Ce n'est pas très différent de exec. Le cas d'utilisation que je trouve pratique est celui de l'utilisation de quelque chose comme Promise.all. Je ne sais pas si la promesse retournée par execfonctionne dans de tels contextes.
Anshul Koka
[RÉPONSE ACCEPTÉE]
Cody
Pouvez-vous s'il vous plaît ajouter un exemple complet avec .exec ()? @AnshulKoka Est-ce que le .exec () rend automatiquement la requête asynchrone ou dois-je ajouter async /
await
Rendre la requête asynchrone nécessitera async / await, donc je ne suis pas sûr de comprendre la question. Juste un préfixe attendez mon exemple pour votre demande d'exemple complet.
Anshul Koka le
8

exec()renverra une promesse si aucun rappel n'est fourni. Le modèle suivant est donc très pratique et générique - il peut bien gérer les rappels ou les promesses:

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

}

Je recommande d'utiliser les promesses de Bluebird avec Mongoose, pour ce faire, utilisez cet appel:

const mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
Alexander Mills
la source
pourquoi avons-nous besoin de bluebird? quand nous avons exec ()
Indraraj26