Mongoose - Co robi funkcja exec?

101

Natknąłem się na fragment kodu Mongoose, który zawierał zapytanie findOne, a następnie funkcję exec ().

Nigdy wcześniej nie widziałem tej metody w Javascript? Co to dokładnie robi?

user439133
źródło

Odpowiedzi:

146

Zasadniczo podczas korzystania z mangusty dokumenty można odzyskać za pomocą pomocników. Każda metoda modelowa, która akceptuje warunki zapytania, może być wykonana za pomocą metody callbacklub exec.

callback:

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

exec:

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

Dlatego jeśli nie przekazujesz wywołania zwrotnego, możesz zbudować zapytanie i ostatecznie je wykonać.

Możesz znaleźć dodatkowe informacje w dokumentach mangusty .

AKTUALIZACJA

Podczas używania Promises w połączeniu z operacjami asynchronicznymi Mongoose należy zwrócić uwagę na to, że zapytania Mongoose nie są Promises. Zapytania zwracają thenable , ale jeśli potrzebujesz prawdziwej obietnicy, powinieneś użyć tej execmetody. Więcej informacji można znaleźć tutaj .

Podczas aktualizacji zauważyłem, że nie odpowiedziałem wprost na pytanie:

Nigdy wcześniej nie widziałem tej metody w Javascript? Co to dokładnie robi?

Cóż, nie jest to natywna metoda JavaScript, ale część interfejsu API Mongoose.

danillouz
źródło
4
Co jeśli ustawiłem mongoose.Promise = require ('bluebird'), czy nadal muszę używać .exec ()? Dzięki.
przyszłego
4
@wayofthefuture Dokumenty są naprawdę zagmatwane w tej sprawie, ale uważam, że nadal musisz wywołać execmetodę. Tak przynajmniej robią w dokumentach. Aby mieć pewność, że możesz się sprawdzić Model.find() instanceof require('bluebird'). Mam nadzieję że to pomoże.
danillouz
1
A potem pojawia się pytanie o inne operacje, takie jak delete i insertMany ... czy exec () będzie konieczne w takich przypadkach? Usunięcie musiałoby użyć jakiegoś zapytania pod maską ...
wayofthefuture
1
exec zwraca również obietnicę, jeśli nie zostanie przekazana żadna funkcja zwrotna, co jest bardzo wygodne, muszę powiedzieć
Alexander Mills,
To może kogoś uratować . Jeśli myślisz, że Model.update () wykona swoje zadanie i nie czekaj na zaktualizowanie niektórych mniej ważnych danych i zwróci odpowiedź do API; Twoja aktualizacja nie zostanie wykonana. Musisz Model.update().exec()się upewnić, że się wykona. Następnie możesz odpowiedzieć na interfejs API bez czekania na aktualizację.
Yogesh
49

Daniel odpowiedział na to całkiem pięknie. Aby rozwinąć wyczerpującą listę sposobów tworzenia i wykonywania zapytań, spójrz na następujące przypadki użycia:

Tworzenie zapytań

Mongoose nie wykona zapytanie do czasu thenlub execzostała wezwana niego. Jest to bardzo przydatne podczas tworzenia złożonych zapytań. Niektóre przykłady mogą obejmować użycie funkcji populatei aggregate.

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

Wykonanie przez callback

Chociaż wielu nie lubi ich ze względu na zagnieżdżanie, zapytania mogą być wykonywane przez dostarczenie opcjonalnego wywołania zwrotnego.

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

Następnie API jako obietnice / A +

Zapytania Mongoose zapewniają thenfunkcję. Nie należy tego mylić z regularnymi obietnicami. Mówiąc najprościej, specyfikacja Promises / A + wymaga, thenaby funkcja działała podobnie jak przyzwyczajeni do obietnic.

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

Funkcja exec

Z dokumentów Mongoose If you need a fully-fledged promise, use the .exec() function.

User.find({name: 'John'}).exec(); // Will execute returning a promise
Anshul Koka
źródło
1
dokumentacja nie wspomina o tym wyraźnie, ale przykłady pokazują, że User.save () również zwraca obietnicę. Oprócz exec () i save (), czy inne metody mongoose w modelu zwracają obietnicę, czy to tylko te dwie?
thetrystero
Jak wskazano powyżej, możesz użyć thenw zapytaniu, aby zwrócić również obietnicę. To niewiele różni się od exec. Przypadek użycia, który uważam za przydatny, to użycie czegoś takiego Promise.all. Nie jestem jednak pewien, czy obietnica zwrócona przez execprace w takich kontekstach.
Anshul Koka
[ZAAKCEPTOWANA ODPOWIEDŹ]
Cody
Czy możesz dodać pełny przykład z .exec ()? @AnshulKoka Czy to dlatego .exec () automatycznie sprawia, że ​​zapytanie jest asynchroniczne, czy powinienem dodać async /
await
Ustawienie asynchroniczności zapytania będzie wymagało async / await, więc nie jestem pewien, czy rozumiem pytanie. Po prostu prefiks czekam na mój przykład na twoją prośbę o kompletny przykład.
Anshul Koka
8

exec()zwróci obietnicę, jeśli nie zostanie udzielone oddzwonienie. Więc następujący wzorzec jest bardzo wygodny i ogólny - może ładnie obsługiwać wywołania zwrotne lub obietnice:

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

}

Polecam używanie obietnic Bluebird z Mongoose, w tym celu użyj tego wywołania:

const mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
Alexander Mills
źródło
dlaczego potrzebujemy bluebird? kiedy mamy exec ()
Indraraj26