Mongoose - Apa yang dilakukan fungsi exec?

100

Saya menemukan sepotong kode Mongoose yang menyertakan query findOne dan kemudian fungsi exec ().

Saya belum pernah melihat metode itu di Javascript sebelumnya? Apa tepatnya yang dilakukannya?

pengguna439133
sumber

Jawaban:

144

Pada dasarnya saat menggunakan luwak, dokumen dapat diambil dengan bantuan pembantu. Setiap metode model yang menerima kondisi query dapat dieksekusi dengan cara callbackatau execmetode.

callback:

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

exec:

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

Oleh karena itu, jika Anda tidak meneruskan callback, Anda dapat membuat kueri dan akhirnya menjalankannya.

Anda dapat menemukan info tambahan di dokumen luwak .

MEMPERBARUI

Sesuatu yang perlu diperhatikan saat menggunakan Promises dalam kombinasi dengan operasi asinkron Mongoose adalah kueri Mongoose bukanlah Promises. Queries mengembalikan thenable , tetapi jika Anda membutuhkan Promise yang nyata, Anda harus menggunakan execmetode ini. Informasi lebih lanjut dapat ditemukan di sini .

Selama pembaruan, saya perhatikan saya tidak secara eksplisit menjawab pertanyaan:

Saya belum pernah melihat metode itu di Javascript sebelumnya? Apa tepatnya yang dilakukannya?

Ini bukan metode JavaScript asli, tetapi bagian dari API Mongoose.

danillouz
sumber
4
Bagaimana jika saya telah menyetel mongoose.Promise = require ('bluebird'), apakah saya masih perlu menggunakan .exec ()? Terima kasih.
wayofthefuture
4
@wayofthefuture Saya menemukan dokumen yang benar-benar membingungkan tentang masalah ini, tetapi saya yakin Anda masih perlu memanggil execmetode ini. Ini yang setidaknya mereka lakukan di dokumen. Yang pasti Anda bisa memeriksanya sendiri dengan Model.find() instanceof require('bluebird'). Semoga ini membantu.
danillouz
1
Dan kemudian ada pertanyaan tentang operasi lain seperti delete dan insertMany ... apakah exec () diperlukan dalam kasus ini? Hapus harus menggunakan semacam kueri di bawah tenda ...
wayofthefuture
1
exec juga mengembalikan sebuah janji, jika tidak ada panggilan balik yang lewat, yang sangat nyaman saya harus katakan
Alexander Mills
Mungkin menyelamatkan seseorang . Jika Anda merasa Model.update () akan melakukan tugasnya dan tidak menunggu beberapa data yang tidak terlalu penting diperbarui dan mengembalikan respons ke API; Pembaruan Anda tidak akan dijalankan. Anda perlu Model.update().exec()memastikan itu akan dijalankan. Kemudian Anda dapat merespons api tanpa menunggu pembaruan.
Yogesh
48

Daniel menjawab ini dengan cukup indah. Untuk menguraikan daftar lengkap cara membuat dan mengeksekusi kueri, lihat kasus penggunaan berikut:

Pembuatan Kueri

Mongoose tidak akan mengeksekusi query sampai thenatau exectelah dipanggil. Ini sangat berguna saat membuat kueri yang kompleks. Beberapa contoh dapat mencakup penggunaan populatedan aggregatefungsi.

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

Eksekusi melalui panggilan balik

Meskipun tidak disukai oleh banyak orang karena sifatnya yang bersarang, kueri dapat dijalankan dengan menyediakan callback opsional.

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

Kemudian API sebagai Promises / A +

Kueri Mongoose memang menyediakan thenfungsi. Jangan disamakan dengan janji biasa. Sederhananya, spesifikasi Promises / A + membutuhkan thenfungsi agar berfungsi seperti yang biasa kita lakukan dengan promise.

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

Fungsi exec

Dari dokumen Mongoose If you need a fully-fledged promise, use the .exec() function.

User.find({name: 'John'}).exec(); // Will execute returning a promise
Anshul Koka
sumber
1
dokumen tidak menyebutkannya secara eksplisit tetapi contoh menunjukkan User.save () mengembalikan sebuah promise juga. Selain dari exec () dan save (), apakah metode luwak lainnya pada model mengembalikan sebuah promise, atau hanya keduanya?
thetrystero
Seperti yang ditunjukkan di atas, Anda bisa menggunakan thenkueri untuk mengembalikan janji juga. Ini tidak jauh berbeda dengan exec. Kasus penggunaan yang menurut saya berguna ini adalah saat menggunakan sesuatu seperti Promise.all. Tidak yakin apakah janji dikembalikan oleh execkarya dalam konteks seperti itu.
Anshul Koka
[JAWABAN DITERIMA]
Cody
Bisakah Anda menambahkan contoh lengkap dengan .exec ()? @AnshulKoka Apakah .exec () secara otomatis membuat kueri asinkron atau haruskah saya menambahkan asinkron / menunggu
O'Dane Brissett
Membuat kueri asynchronous akan membutuhkan async / await jadi saya tidak yakin apakah saya memahami pertanyaannya. Awalan saja menunggu contoh saya untuk permintaan Anda untuk contoh lengkap.
Anshul Koka
7

exec()akan mengembalikan janji jika tidak ada panggilan balik yang diberikan. Jadi, pola berikut sangat nyaman dan umum - ini dapat menangani callback atau promise dengan baik:

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

}

Saya merekomendasikan menggunakan janji Bluebird dengan Mongoose, untuk melakukan itu, gunakan panggilan ini:

const mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
Alexander Mills
sumber
mengapa kita membutuhkan bluebird? ketika kita memiliki exec ()
Indraraj26