Javascript Express.js异步问题

Javascript Express.js异步问题,javascript,node.js,express,Javascript,Node.js,Express,我对节点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) { _.eac

我对节点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数组发送到客户端?

我建议您研究使用承诺。然后,您可以在迭代时创建一个异步承诺数组,然后在返回“发送”数据之前等待所有承诺完成

Q()是一个很好的库

像这样的事情也许

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);
    });
    });

}

将计数器初始化为您拥有的歌曲数。然后,你在循环中为每首歌减量。当您达到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,增加它,并在达到歌曲数时进行检查。这只是习惯的问题,我通常更喜欢这种情况下的倒计时逻辑。

它实际上等待每个循环完成,只是你的每个循环在你所有的函数调用完成之前完成。因为functions.generateViewData是异步的,\每次迭代都在functions.generateViewData调用回调函数之前返回

我建议您使用,它的功能非常适合您的用例。你可以这样做:

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函数对其进行进一步整理