Мангуст - что делает функция exec?

101

Я наткнулся на фрагмент кода Mongoose, который включал запрос findOne, а затем функцию exec ().

Я никогда раньше не видел этот метод в Javascript? Что именно он делает?

user439133
источник

Ответы:

147

Обычно при использовании мангуста документы можно получить с помощью помощников. Каждый метод модели, который принимает условия запроса, может быть выполнен с помощью метода callbackили execметода.

callback:

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

exec:

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

Поэтому, когда вы не передаете обратный вызов, вы можете создать запрос и в конечном итоге выполнить его.

Вы можете найти дополнительную информацию в документации мангуста .

ОБНОВИТЬ

При использовании обещаний в сочетании с асинхронными операциями Mongoose следует отметить, что запросы Mongoose не являются обещаниями. Запросы действительно возвращают значение , но если вам нужно настоящее обещание, вы должны использовать этот execметод. Более подробную информацию можно найти здесь .

Во время обновления я заметил, что не ответил прямо на вопрос:

Я никогда раньше не видел этот метод в Javascript? Что именно он делает?

Ну, это не собственный метод JavaScript, а часть API Mongoose.

Даниллуз
источник
4
Что, если я установил mongoose.Promise = require ('bluebird'), мне все равно нужно использовать .exec ()? Спасибо.
wayofthefuture
4
@wayofthefuture Я считаю, что документы действительно сбивают с толку по этому поводу, но я считаю, что вам все равно нужно вызывать execметод. По крайней мере, это то, что они делают в документации. Конечно, вы можете проверить себя с помощью Model.find() instanceof require('bluebird'). Надеюсь это поможет.
danillouz
1
И тогда возникает вопрос о других операциях, таких как delete и insertMany ... будет ли в этих случаях необходима функция exec ()? Удалить придется использовать какой-то запрос под капотом ...
wayofthefuture
1
exec также возвращает обещание, если обратный вызов не передан, что, я должен сказать, очень удобно,
Александр Миллс
Это может кого-то спасти . Если вы думаете, что Model.update () выполнит свою работу и не дожидаетесь обновления некоторых не очень важных данных и не вернете ответ API; Ваше обновление не будет выполнено. Вам нужно Model.update().exec()убедиться, что он будет выполнен. Затем вы можете ответить на api, не дожидаясь обновления.
Йогеш
49

Дэниел ответил на это довольно красиво. Чтобы разработать исчерпывающий список способов построения и выполнения запросов, рассмотрите следующие варианты использования:

Построение запросов

Mongoose не выполнит запрос до тех пор , thenили execбыла вызвана на него. Это очень полезно при построении сложных запросов. Некоторые примеры могут включать в себя , используя populateи aggregateфункции.

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

Выполнение через обратный вызов

Хотя это не нравится многим из-за его вложенности, запросы можно выполнять, предоставляя дополнительный обратный вызов.

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

Тогда API как обещание / 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

Функция exec

Из документации Mongoose If you need a fully-fledged promise, use the .exec() function.

User.find({name: 'John'}).exec(); // Will execute returning a promise
Аншул Кока
источник
1
в документации это не упоминается явно, но в примерах показано, что User.save () также возвращает обещание. Помимо exec () и save (), какие-либо другие методы мангуста в модели возвращают обещание, или это только эти два?
thetrystero
Как указано выше, вы также можете использовать thenзапрос для возврата обещания. Это не сильно отличается от exec. Вариант использования, который я считаю удобным, - это использование чего-то вроде Promise.all. Не уверен, что обещание, возвращаемое функцией, execработает в таких контекстах.
Аншул Кока 05
[ПРИНЯТ ОТВЕТ]
Коди,
Не могли бы вы добавить полный пример с .exec ()? @AnshulKoka Это то, что .exec () автоматически делает запрос асинхронным, или я должен добавить async / await
О'Дейн Бриссетт,
Для выполнения асинхронного запроса потребуется async / await, поэтому я не уверен, понимаю ли я вопрос. Просто префикс ждите моего примера для вашего запроса для полного примера.
Аншул Кока
8

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

}

Я рекомендую использовать обещания Bluebird с Mongoose, для этого используйте этот вызов:

const mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
Александр Миллс
источник
зачем нам синяя птица? когда у нас есть exec ()
Indraraj26