使用mongoose查询来自db和Q for 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
之前完成查询而不进行大量草率回调?
答案 0 :(得分:19)
另一个建议是使用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
一个。
答案 1 :(得分:5)
“我如何继续承诺”这个问题的答案几乎总是与.then
一致。它是;
的承诺类比,它终止了一个异步语句。您可以在其中返回承诺,并在继续之前将其解包。
Q.all(promises).then(function(users){
SomeOtherFunction(users);
});
或只是Q.all(promise).then(SomeOtherFunction)
您还需要findOne来实际返回承诺。您可以使用调用节点函数的Q.nfcall
或promisify it yourself。
Q.all
所做的是接受一系列承诺,并在所有的时候完成,并在其中一个拒绝时拒绝。您可能希望在任何查询失败时附加.catch
处理程序,或使用.done
来表示链的结尾。像Bluebird这样的其他承诺库甚至会在没有.done
或添加显式处理程序的情况下为您挑选错误,遗憾的是Q不会这样做。
答案 2 :(得分:4)
您也可以使用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);
});
答案 3 :(得分:0)
在这里可以使用Promise API:
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
from matplotlib import colors as mcolors
width_dist = 10
depth_dist = 10
levels = 5
def bintree_level(levels, x, y, width):
segments = []
xl = x + depth_dist
yl = y - width / 2
xr = x + depth_dist
yr = y + width / 2
segments.append([[x, y], [xl, yl]])
segments.append([[x, y], [xr, yr]])
if levels > 1:
segments += bintree_level(levels - 1, xl, yl, width / 2)
segments += bintree_level(levels - 1, xr, yr, width / 2)
return segments
segs = bintree_level(levels, 0, 0, width_dist)
colors = [mcolors.to_rgba(c)
for c in plt.rcParams['axes.prop_cycle'].by_key()['color']]
line_segments = LineCollection(segs, linewidths=1, colors=colors, linestyle='solid')
fig, ax = plt.subplots()
ax.set_xlim(-1, levels * depth_dist + 1)
ax.set_ylim(-1.5*width_dist, 1.5*width_dist)
ax.add_collection(line_segments)
plt.show()