Мангуст - Що виконує функція exec?


100

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

Я ніколи раніше не бачив цього методу в Javascript? Що саме робить?

Відповіді:


144

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

callback:

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

exec:

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

Тому, коли ви не передаєте зворотний виклик, ви можете побудувати запит і врешті виконати його.

Ви можете знайти додаткову інформацію в документах мангуста .

ОНОВЛЕННЯ

Щось, на що слід звернути увагу при використанні Promises у поєднанні з асинхронними операціями Mongoose, це те, що запити Mongoose не є Promises. Запити повертаються підданими , але якщо вам потрібна справжня Обіцянка, вам слід скористатися execметодом. Більше інформації можна знайти тут .

Під час оновлення я помітив, що я не відповідав прямо на питання:

Я ніколи раніше не бачив цього методу в Javascript? Що саме робить?

Ну це не рідний метод JavaScript, а частина API Mongoose.


4
Що робити, якщо я встановив mongoose.Promise = require ('bluebird'), чи все-таки мені потрібно використовувати .exec ()? Дякую.
виходу

4
@wayofthefuture Я вважаю, що документи справді заплутані з цього приводу, але я вважаю, що вам все одно потрібно зателефонувати до execметоду. Це те, що вони роблять принаймні в документах. Щоб бути впевненим, що ви можете перевірити себе Model.find() instanceof require('bluebird'). Сподіваюся, це допомагає.
danillouz

1
І тоді виникає питання про інші операції, такі як delete і insertMany ... чи буде в цих випадках необхідний exec ()? Delete мав би використовувати якийсь запит під капотом ...
wayofthefuture

1
exec також повертає обіцянку, якщо не буде передано зворотний виклик, що дуже зручно, я повинен сказати
Alexander Mills

Це може когось врятувати . Якщо ви думаєте, що Model.update () зробить свою справу, і не чекайте оновлення деяких не дуже важливих даних і повертайте відповідь на API; Ваше оновлення не буде запущено. Вам потрібно Model.update().exec()переконатися, що він буде виконаний. Тоді ви можете відповісти на api, не чекаючи оновлення.
Йогеш

48

Даніель відповів на це досить красиво. Щоб детально розробити вичерпний перелік способів побудови та виконання запитів, перегляньте такі випадки використання:

Побудова запитів

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

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

Виконання за допомогою зворотного дзвінка

Хоча багатьом це не подобається через його вкладеність, запити можуть виконуватися шляхом надання необов’язкового зворотного виклику.

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

Потім API як Promises / A +

Запити мангуста дійсно надають 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працює в такому контексті.
Аншул Кока,

[ПРИЙНЯТИ ВІДПОВІДЬ]
Коді

Ви можете додати повний приклад із .exec ()? @AnshulKoka Це те, що .exec () автоматично робить запит асинхронним, або я повинен додати async / await
O'Dane Brissett

Щоб зробити запит асинхронним, буде потрібно async / await, тому я не впевнений, що розумію питання. Просто префікс чекає мого прикладу для вашого запиту на повний приклад.
Аншул Кока,

7

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.