繁体   English   中英

Express.js异步问题

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM