我试图从MongoDB获取多个文档并将所有数据发送到数组中,但我很难理解如何使用事件驱动的Node.js来完成这项工作。
问题是,在执行dataArray.push(tempObject)
时,tempObject["data"] = tempDataArray
仍未执行。
我的代码如下所示:
app.post('/api/charts', function(req, res) {
var names = req.body.names;
var categories = req.body.categories;
var dataArray = [];
for (i = 0; i < names.length; i++) {
var tempObject = {};
tempObject["name"] = names[i];
Company.find({ name : names[i] }, function(err, result) {
if (err) {
throw err;
}
var tempDataArray = [];
for (k = 0; k < categories.length; k++) {
var tempDataObject = {};
tempDataObject["name"] = categories[k];
tempDataObject["numbers"] = result[0]["data"][categories[k]]["numbers"];
tempDataObject["dates"] = result[0]["data"][categories[k]]["dates"];
tempDataArray.push(tempDataObject);
}
tempObject["data"] = tempDataArray;
});
dataArray.push(tempObject);
}
res.send(dataArray);
});
任何关于如何正确达到预期结果的建议都将受到赞赏。
答案 0 :(得分:0)
使用此库
https://github.com/caolan/async
使用此代码,您的代码将如下所示:
var async = require("async");
app.post('/api/charts', function(req, res) {
var names = req.body.names;
var categories = req.body.categories;
var dataArray = [];
async.forEach(names, function(name, callback){
var tempObject = {};
tempObject["name"] = name;
Company.find({ name : name }, function(err, result) {
if (err) {
callback(err);
} else {
var tempDataArray = [];
for (k = 0; k < categories.length; k++) {
var tempDataObject = {};
tempDataObject["name"] = categories[k];
tempDataObject["numbers"] = result[0]["data"][categories[k]]["numbers"];
tempDataObject["dates"] = result[0]["data"][categories[k]]["dates"];
tempDataArray.push(tempDataObject);
}
tempObject["data"] = tempDataArray;
dataArray.push(tempObject);
callback();
}
});
}, function(err){
if(err){
res.send(err);
} else {
res.send(dataArray);
}
});
});
答案 1 :(得分:0)
Company.find()
方法采用回调函数作为第二个参数。在从数据库中检索公司数据之后,将调用此回调。这意味着它可以在几毫秒到几毫秒之间的任何地方,直到在调用Company.find()
方法之后调用它。但是Company.find()
之后的代码不会被延迟;它将被立即调用。因此,回调延迟是dataArray.push(tempObject)
之前始终调用tempObject["data"] = tempDataArray
的原因。
除此之外,外部for循环将同步运行,并且在每次迭代时将进行单独的DB调用。这不是理想的,所以我们希望将这个for循环引入回调。所以我们可以这样做:
app.post('/api/charts', function(req, res) {
var names = req.body.names;
var categories = req.body.categories;
// we just do one DB query where all the data we need is returned
Company.find({ name : names }, function(err, result) {
if (err) {
throw err;
}
var dataArray = [];
// we iteratre through each result in the callback, not outside it since
// that would cause blocking due to synchronous operation
for (i = 0; i < result.length; i++) {
var tempObject = {};
tempObject["name"] = result[i].name;
var tempDataArray = [];
for (k = 0; k < categories.length; k++) {
var tempDataObject = {};
tempDataObject["name"] = categories[k];
tempDataObject["numbers"] = result[i]["data"][categories[k]]["numbers"];
tempDataObject["dates"] = result[i]["data"][categories[k]]["dates"];
tempDataArray.push(tempDataObject);
}
tempObject["data"] = tempDataArray;
dataArray.push(tempObject);
}
res.send(dataArray);
});
});
有许多抽象节点事件驱动特性的方法,例如Promises(可以在ECMA Script 6或Promise库中访问,如Bluebird,Async等)。但以上是一种基本的回调方法,通常用于Express应用程序。
答案 2 :(得分:0)
只需改变一下:
line-height
要:
tempObject["data"] = tempDataArray;
});
dataArray.push(tempObject);