[英]Express.js async issue
我对节点js的异步性质有疑问,我有一个此功能
var sendData = function(req, res) {
var requestId = req.params.id;
var dataForSend = [];
database.collection('songs').find({player_id:new ObjectID(requestId)}).toArray(function(err, player) {
_.each(songs , function(song){
var songID = song._id;
song[song] = song;
functions.generateViewData(song,data,false, function(playerData, song) {
var dataForSong = {
// some code here
}
dataForSend.push(dataForChart);
console.log("Kako ovo ne radi leb ti jebem" + JSON.stringify(dataForChart));
});
});
res.send(dataForSend);
});
}
我的问题是应用程序不必等待每个循环完成并填充dataForSend数组,而每次都需要im res.send(dataForSend)空数组,如何等待此循环完成然后将dataForSend数组发送给客户端?
初始化一个计数器以获取您拥有的歌曲数。 然后,您可以为每首工作的歌曲在循环中减少它。 当您达到0时,您将发送数据。
var songsRemaining = songs.length;
_.each(songs , function(song){
var songID = song._id;
song[song] = song;
functions.generateViewData(song,data,false, function(playerData, song) {
var dataForSong = {
// some code here
}
dataForSend.push(dataForChart);
songsRemaining--;
if (songsRemaining === 0) {
res.send(dataForSend);
}
});
});
您还可以反转逻辑,将计数器初始化为0,将其递增,并检查何时达到歌曲数量。 这只是一个习惯问题,我通常更喜欢这种情况下的倒数计时逻辑。
我建议您考虑使用诺言。 然后,您可以在迭代时创建一个异步承诺数组,然后等待所有承诺完成后再返回“发送”数据。
Q( https://github.com/kriskowal/q )是一个很棒的Promise库。
这样的东西也许...
var Q = require("Q");
var sendData = function(req, res) {
var requestId = req.params.id;
var dataForSend = [];
database.collection('songs').find({player_id:new ObjectID(requestId)}).toArray(function(err, player) {
var promises = [];
_.each(songs , function(song){
var songID = song._id;
song[song] = song;
var promise = Q.fcall(function() {
functions.generateViewData(song,data,false, function(playerData, song) {
var dataForSong = {
// some code here
}
dataForSend.push(dataForChart);
console.log("Kako ovo ne radi leb ti jebem" + JSON.stringify(dataForChart));
});
});
promises.push(promise);
});
Q.all(promises).then(function() {
res.send(dataForSend);
});
});
}
实际上,它等待_.each循环完成,只是您的_.each循环在所有function.generateViewData调用完成之前完成。 由于functions.generateViewData是异步的,因此_.each迭代在function.generateViewData调用回调函数之前返回。
我建议您使用asyncjs ,它具有async.each函数,非常适合您的用例。 您可以这样做:
var sendData = function(req, res) {
var requestId = req.params.id;
var dataForSend = [];
database.collection('songs').find({player_id:new ObjectID(requestId)}).toArray(function(err, player) {
async.each(songs,
function(song,callback){
functions.generateViewData(song,data,false, function(playerData, song) {
var dataForSong = {
// some code here
}
dataForSend.push(dataForChart);
console.log("Kako ovo ne radi leb ti jebem" + JSON.stringify(dataForChart));
//you call the callback with no parameters or null if no error occurs
callback();
});
},
function(err){
//since you never called callback with an error err will always be null and this function will be called when all your songs finished processing
res.send(dataForSend);
}
);
});
}
您还可以使用其他asyncjs函数对其进行整理
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.