我是javascript的新手。
我试过使用async.parellel函数。 得到" reviewArr"并将其归还。
请参阅我的代码。
app.get('/api/wherecritique/reviews/search/:author', function(req,res){
var reviewArr = [];
Critique.find({author:req.params.autho}, function(err,cris){
var i =0;
var f = function(reviewID)
{
Review.findOne({id:reviewID}, function(err, review)
{
reviewArr.push(review);
}
}
var tasks = {};
for(var j =0; j<cris.length; j++)
{
tasks['func'+j] = f(cris[j].reviewID);
}
async.parallel(tasks, function(err, results){
console.log(results);
res.json(reviewArr);
});
});
});
我使用了mongoose + express + node.js。 Critique,Review是模型(mongoose schema)。
当我运行此代码时,我收到此消息。 &#34;任务不是一个功能&#34;
请帮助我如何解决此错误? 问候。
答案 0 :(得分:4)
您没有正确设置功能。期望的参数是带有function()
参数的callback
包装器,当包含的异步函数完成时,它将被传递给它。
你真的只想要async.map
而不是你正在做的事情,因为它的输出是来自循环调用的结果数组。因此无需将结果推送到外部变量中:
app.get('/api/wherecritique/reviews/search/:author', function(req,res) {
Critique.find({author: req.params.author}, function(err,cris) {
async.map(
cris.map( c => c.reviewID ),
function(id, callback) {
Review.findOne({ id: id }, callback);
},
function(err,results) {
if (err) throw err; // or something with err
console.log(results);
res.json(results);
}
);
});
});
但是说实话,你应该在这里使用Promise而不是导入外部库
app.get('/api/wherecritique/reviews/search/:author', function(req,res) {
Critique.find({author: req.params.author}, function(err,cris) {
Promise.all(
cris.map( c => Review.findOne({ id: c.reviewID }) )
).then( results => {
console.log(results);
res.json(results);
}).catch( e => console.error(e) );
});
});
或者使用async/await
以更现代的方式:
app.get('/api/wherecritique/reviews/search/:author', async (req,res) => {
try {
let cris = await Critique.find({author: req.params.author});
let results = Promise.all(
cris.map( c => Review.findOne({ id: c.reviewID }) )
);
console.log(results);
res.json(results);
} catch(e) {
console.error(e);
}
});
但实际上,这与JavaScript完全无关,你真的应该使用MongoDB功能。
支持$lookup
:
app.get('/api/wherecritique/reviews/search/:author', async (req,res) => {
try {
let results = await Critique.aggregate([
{ $match: { author: req.params.author } },
{ $lookup: {
from: Review.collection.name,
localField: 'reviewID',
foreignField: 'id'
as: 'reviews'
}},
{ $unwind: '$reviews' }
]);
results = results.map( r => r.reviews );
console.log(results);
res.json(results);
} catch(e) {
console.error(e);
}
});
或者,如果您没有,那么只需将所有id
值传递给$in
:
app.get('/api/wherecritique/reviews/search/:author', async (req,res) => {
try {
let cris = await Critique.find({ author: req.params.author });
let results = await Review.find({ id: { $in: cris.map( c => c.reviewID ) } });
console.log(results);
res.json(results);
} catch(e) {
console.error(e);
}
});
这意味着根据您的MongoDB版本对数据库进行“一次”或“两次”实际调用。根本不需要循环异步调用。
最后,正如以上所有解释的那样,真的没有必要,但async.parallel
的正确用法是:
app.get('/api/wherecritique/reviews/search/:author', (req,res) => {
Critique.find({author: req.params.author}, (err,cris) => {
var tasks = cris.map( c => (callback) =>
Review.findOne({ id: c.reviewID }, callback);
);
async.parallel(
tasks,
(err,results) => {
if (err) throw err; // or something
console.log(results);
res.json(results);
}
)
});
});