Mongoose и promises: как получить массив результатов запроса?
Использование mongoose для запроса результатов из db и Q для promises, но мне трудно оборачивать голову, просто получая список доступных пользователей. В настоящее время у меня есть что-то вроде этого:
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 )
Как мне решить, заканчивать ли запросы до SomeOtherFunction
, не выполняя тонны неаккуратных обратных вызовов?
Ответы
Ответ 1
Другое предложение - использовать MongoDB $in
для передачи массива в find
и эффективно получать большой набор результатов. Каждый из них будет объектом Mongoose.
var promise = people.find({ _id: { $in: someArrayOfIds }).exec();
promise.then(function(arrayOfPeople) {
// array of people ... do what you want here...
});
Это будет намного эффективнее, чем создание нескольких запросов, по одному для каждого _id
.
Ответ 2
Ответ на вопрос "как я могу продолжить с promises" почти всегда с .then
. Это обетованная аналогия ;
и завершает асинхронное утверждение. Вы можете вернуть promises в него, и он будет распаковывать их перед продолжением.
Q.all(promises).then(function(users){
SomeOtherFunction(users);
});
Или просто Q.all(promise).then(SomeOtherFunction)
Вам также понадобится findOne, чтобы на самом деле вернуть promises. Вы можете либо использовать Q.nfcall
, который вызывает функцию node, либо обещает его самостоятельно.
То, что Q.all
делает, принимает массив из promises и выполняет, когда все они делают и отклоняют, когда один из них отклоняется. Возможно, вы захотите добавить обработчик .catch
в случае отказа любого из запросов или использования .done
, чтобы обозначить конец цепочки. Другие библиотеки обещаний, такие как Bluebird, будут забирать ошибки для вас даже без .done
или добавления явного обработчика, к сожалению Q не делает этого.
Ответ 3
Вы также можете использовать q (npm install 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);
});