簡體   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