พังพอน - exec function ทำอะไร?


103

ฉันเจอโค้ดพังพอนชิ้นหนึ่งที่มีเคียวรี findOne และฟังก์ชัน exec ()

ฉันไม่เคยเห็นวิธีการนั้นใน Javascript มาก่อน? มันทำอะไรกันแน่?

คำตอบ:


151

โดยทั่วไปเมื่อใช้พังพอนสามารถดึงเอกสารได้โดยใช้ตัวช่วย ทุกเมธอดโมเดลที่ยอมรับเงื่อนไขเคียวรีสามารถดำเนินการได้โดยใช้ a callbackหรือexecเมธอด

callback:

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

exec:

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

ดังนั้นเมื่อคุณไม่ส่งการโทรกลับคุณสามารถสร้างแบบสอบถามและดำเนินการได้ในที่สุด

ท่านสามารถหาข้อมูลเพิ่มเติมในเอกสารพังพอน

อัปเดต

สิ่งที่ควรทราบเมื่อใช้Promisesร่วมกับการดำเนินการแบบ async ของ Mongoose คือการค้นหาพังพอนไม่ใช่คำสัญญา ข้อความค้นหาจะส่งคืนที่ตอบได้ แต่ถ้าคุณต้องการคำสัญญาจริงคุณควรใช้execวิธีนี้ ข้อมูลเพิ่มเติมสามารถพบได้ที่นี่

ในระหว่างการอัปเดตฉันสังเกตเห็นว่าฉันไม่ได้ตอบคำถามอย่างชัดเจน:

ฉันไม่เคยเห็นวิธีการนั้นใน Javascript มาก่อน? มันทำอะไรกันแน่?

มันไม่ใช่วิธีดั้งเดิมของ JavaScript แต่เป็นส่วนหนึ่งของ Mongoose API


4
จะเกิดอะไรขึ้นถ้าฉันตั้งพังพอนสัญญา = ต้องการ ('bluebird') ฉันยังต้องใช้. exec () อยู่ไหม ขอบคุณ.
wayofthefuture

4
@wayofthefuture ฉันพบว่าเอกสารสับสนเกี่ยวกับเรื่องนี้จริงๆ แต่ฉันเชื่อว่าคุณยังต้องเรียกใช้execวิธีการนี้ นี่คือสิ่งที่พวกเขาทำในเอกสารอย่างน้อยที่สุด Model.find() instanceof require('bluebird')เพื่อให้แน่ใจว่าคุณสามารถตรวจสอบตัวเองด้วย หวังว่านี่จะช่วยได้
danillouz

1
แล้วมีคำถามเกี่ยวกับการดำเนินการอื่น ๆ เช่น delete และ insertMany ... exec () จำเป็นในกรณีเหล่านี้หรือไม่? การลบจะต้องใช้ข้อความค้นหาบางอย่างที่อยู่ใต้ฝากระโปรง ...
wayofthefuture

1
ผู้บริหารยังคืนคำสัญญาหากไม่มีการโทรกลับซึ่งสะดวกมากฉันต้องบอกว่า
Alexander Mills

มันอาจช่วยใครบางคนได้ หากคุณคิดว่า Model.update () จะทำงานได้และอย่ารอให้ข้อมูลที่ไม่สำคัญบางอย่างได้รับการอัปเดตและตอบกลับไปยัง API การอัปเดตของคุณจะไม่ทำงาน คุณต้องModel.update().exec()แน่ใจว่าจะดำเนินการได้ จากนั้นคุณสามารถตอบสนองต่อ API ได้โดยไม่ต้องรอการอัปเดต
Yogesh

52

แดเนียลตอบเรื่องนี้ได้อย่างสวยงามทีเดียว ในการอธิบายรายละเอียดเกี่ยวกับวิธีการสร้างและดำเนินการสืบค้นโดยละเอียดให้ดูที่กรณีการใช้งานต่อไปนี้

อาคารแบบสอบถาม

พังพอนจะไม่ดำเนินการค้นหาจนกว่าthenหรือexecถูกเรียกใช้ สิ่งนี้มีประโยชน์มากเมื่อสร้างแบบสอบถามที่ซับซ้อน ตัวอย่างบางส่วนอาจรวมถึงการใช้ฟังก์ชันpopulateและaggregate

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

ดำเนินการผ่านการโทรกลับ

แม้ว่าหลาย ๆ คนจะไม่ชอบเนื่องจากลักษณะการซ้อนกัน แต่การสืบค้นสามารถดำเนินการได้โดยระบุการเรียกกลับที่เป็นทางเลือก

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

จากนั้น API เป็นสัญญา / A +

คำค้นหาพังพอนมีthenฟังก์ชัน นี่ไม่ต้องสับสนกับคำสัญญาปกติ พูดง่ายๆก็คือข้อกำหนดของสัญญา / 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 docs 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ทำงานในบริบทดังกล่าวหรือไม่
Anshul Koka

คุณช่วยเพิ่มตัวอย่างที่สมบูรณ์ด้วย. exec () ได้ไหม @AnshulKoka เป็นไหมที่. exec () ทำให้แบบสอบถามไม่ตรงกันโดยอัตโนมัติหรือฉันควรเพิ่ม async / await
O'Dane Brissett

การสร้างแบบสอบถามแบบอะซิงโครนัสจะต้องใช้ async / await ดังนั้นฉันจึงไม่แน่ใจว่าเข้าใจคำถามหรือไม่ เพียงคำนำหน้ารอตัวอย่างของฉันสำหรับคำขอของคุณสำหรับตัวอย่างที่สมบูรณ์
Anshul Koka

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 สัญญากับพังพอนในการทำเช่นนั้นใช้การโทรนี้:

const mongoose = require('mongoose');
mongoose.Promise = require('bluebird');

ทำไมเราถึงต้องการ bluebird? เมื่อเรามี exec ()
อินทราราช 26
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.