2014-04-01 16 views
11

Sử dụng mongoose để truy vấn kết quả từ db và Q cho các lời hứa, nhưng việc tìm kiếm khó khăn để bao quanh đầu tôi chỉ nhận được danh sách người dùng có sẵn. Hiện nay tôi có một số cái gì đó như thế này:Mongoose và hứa hẹn: làm thế nào để có được một loạt các kết quả truy vấn?

var checkForPerson = function(person) { 
    people = mongoose.model('Person', Person) 

    return people.findOne({"_id": person }, function(err, doc) { 
     if (err) console.log(err) 

     if (doc !== null) { 
      return doc 
     } else { 
      console.log('no results') 
     } 

    }) 
} 

var promises = someArrayOfIds.map(checkForPerson); 

// this is where I would like to have an array of models 
var users = Q.all(promises) 

//this fires off before the people.findOne query above to users is undefined 
SomeOtherFunction(users) 

Làm thế nào tôi sẽ đi về việc có các truy vấn kết thúc trước khi SomeOtherFunction mà không làm tấn callbacks cẩu thả?

Trả lời

18

Một đề xuất khác là sử dụng toán tử $in của MongoDB để chuyển một mảng tới find và nhận được một tập hợp lớn các kết quả một cách hiệu quả. Mỗi người sẽ là một đối tượng Mongoose.

var promise = people.find({ _id: { $in: someArrayOfIds }).exec(); 
promise.then(function(arrayOfPeople) { 
    // array of people ... do what you want here... 
}); 

Điều này sẽ hiệu quả hơn nhiều so với thực hiện nhiều yêu cầu, một yêu cầu cho mỗi _id.

+1

Không bao giờ biết về điều đó '$ in', tôi chắc chắn sẽ thử điều này! –

+1

@ delboud op nếu đây là câu trả lời mà cuối cùng giải quyết vấn đề của bạn, bạn nên xem xét chấp nhận nó hơn tôi mà bạn vừa chấp nhận. Trong tất cả sự trung thực trong khi câu trả lời của tôi mang lại nhiều nền lý thuyết và thông tin hữu ích hơn về lời hứa IMO - đây là câu trả lời thực tế cho những người phải đối mặt với vấn đề này ở Mongoose. Bạn có thể upvote câu trả lời của tôi nếu bạn tìm thấy nó hữu ích nhưng tôi tất cả cho các giải pháp thực tế :) –

+1

Tôi đã thực sự đấu tranh với những lời hứa để bạn trả lời câu hỏi của tôi, nhưng, ông đã cho tôi cái nhìn sâu sắc về một tính năng. Dù bằng cách nào với tôi :) –

5

Câu trả lời của câu hỏi "làm cách nào để tiếp tục với lời hứa" hầu như luôn luôn với .then. Đây là lời hứa tương tự của ; và nó chấm dứt một câu lệnh không đồng bộ. Bạn có thể trả lại lời hứa trong đó và nó sẽ gỡ bỏ chúng trước khi tiếp tục.

Q.all(promises).then(function(users){ 
    SomeOtherFunction(users); 
}); 

Hoặc đơn giản là Q.all(promise).then(SomeOtherFunction)

Bạn cũng sẽ cần findOne để thực sự trở lại hứa hẹn. Bạn có thể sử dụng Q.nfcall gọi hàm nút hoặc promisify it yourself.

Điều gì Q.all chấp nhận một loạt các lời hứa và hoàn thành khi tất cả trong số đó thực hiện và từ chối khi một trong số họ từ chối. Bạn có thể muốn thêm một trình xử lý .catch trong trường hợp bất kỳ truy vấn nào không thành công hoặc sử dụng .done để biểu thị sự kết thúc của một chuỗi. Các thư viện hứa hẹn khác như Bluebird sẽ nhận lỗi cho bạn ngay cả khi không có .done hoặc thêm một trình xử lý rõ ràng, đáng buồn là Q không làm điều này.

+4

FYI:. 'FindOne() exec() 'trả về một Promise. – WiredPrairie

+2

@WiredPrairie trong trường hợp đó - OP chắc chắn nên sử dụng 'findOne (..). Exec' thay vì làm phiền với nfcall hoặc quảng bá nó theo cách thủ công. OP - cũng lưu ý điều này có nghĩa là bạn không cần tất cả các công cụ '.if (err)', hứa hẹn sẽ xử lý nó cho bạn. –

4

Bạn cũng có thể sử dụng q (NPM cài đặt q)

var q = require('q') 
, aPromise = mongooseModelA.find({_id: aId}).exec() 
, bPromise = mongooseModelB.find({_id: bId}).exec(); 

q.all([aPromise, bPromise]).then(function(bothA_and_B) { 
    console.log(bothA_and_B); 
}); 
Các vấn đề liên quan