2015-04-29 28 views
-1

我的var movieRecommendation正在從來自Mongo DB的數據中填充。問題是貓鼬Movie.findOne()電話是asycn電話,它不允許我得到我最後填充的movieRecommendation,我需要發回作爲迴應。使用查詢查詢Mongoose異步調用問題

exports.getRecommendation=function(req,res){ 
var movieRecommendation = []; 
var id=req.params.id; 
console.log('----- Get User Recommendation - ' + id); 
var url = 'http://52.8.48.113:8080/recommender-server/recommender/v1/recommendations/'+id+'.do'; 
//make http get request 
request({ 
    url: url, 
    json: true 
}, function (error, response, recommendations) { 
     // res.json(recommendations); 

    if (!error && response.statusCode === 200) { 
     recommendations.forEach(function(entry) { 

      **Movie.findOne({'id':parseInt(entry.itemId)},function(err, movieData){** 
       entry.movie = movieData; 
       movieRecommendation.push(entry); 
       //console.log('rec', movieRecommendation); 
       console.log(movieRecommendation.length); 
      }); 


     }); 

    } 
    console.log("====Final========"+movieRecommendation.length); 
    //Output = 0 

}); 

    res.json(movieRecommendation); // Here movieRecommendation is coming as black Array 

}; 

請讓我知道我能得到最後填充在結束movieRecommendation變種,以使其可用於響應。

+2

不要使用常規'for'循環來執行異步調用,因爲它們不會等待異步調用返回。嘗試['async.each'](https://www.npmjs.com/package/async#each)或實現promise的模塊,如'q'(https://www.npmjs.com/package/q )或「bluebird」(https://www.npmjs.com/package/async#each)。 –

回答

0

對於這種類型的問題,我們可以使用Async庫。要在所有操作完成後最終填充數據,我們可以使用async.each異步庫收集。

例如: 注:此命令 NPM安裝異步安裝異步使用異步庫

var async = require("async"); 

    var recomenmendations = [{"data2" : "value2"} , {"data1" : "value2"}, {"data3" : "value3"}, {"data4" : "value4"} ] 

    var movieRecommendation = []; 

    async.each(recomenmendations, 

     function(recomenmendationItem, callback){ 


      console.log("Here you can query the required data using current recomenmendations ITEM"); 
      console.log(recomenmendationItem); 
      callback(); 

      // Movie.find({'id':parseInt(recomenmendationItem.itemId)},function(err, movieData){ 

      //   recomenmendationItem.movie = movieData; 
      //   movieRecommendation.push(entry); 
      //  callback();   
      // }); 



     }, 

     function(err){ 

     console.log("here you can send your resopnse"); 
     console.log("This section will be executed once all the recomenmendations are processed"); 
     //res.json(movieRecommendation) 

     } 
    ); 

您可以查詢的MongoDB如圖所示與評論部分。一旦對迭代執行了所有操作,您應該使用回調()

+0

嗨Prabhu,給定代碼正常工作正常,但是當我在回調()之前再次進行Mongo調用時,我面臨着與之前相同的問題。 –

-1

我已經按照上面給出的建議嘗試過了。 var async = require(「async」);

var recomenmendations = [{"data2" : "value2"} , {"data1" : "value2"}, {"data3" : "value3"}, {"data4" : "value4"} ] 

var movieRecommendation = []; 

async.each(recomenmendations, 

    function(recomenmendationItem, callback){ 


     console.log("Here you can query the required data using current recomenmendations ITEM"); 
     console.log(recomenmendationItem); 


     // Movie.find({'id':parseInt(recomenmendationItem.itemId)},function(err, movieData){ 

       recomenmendationItem.movie = movieData; 
       movieRecommendation.push(entry); 
       console.log("any data"); // line y  
      }); 

callback(); 

    }, 

    function(err){ 

    console.log("here you can send your resopnse"); // line x 
    console.log("This section will be executed once all the  
    recomenmendations are processed"); 
    //res.json(movieRecommendation) 

    } 
); 

但還是面臨同樣的問題行x在行y之前打印,這又是同樣的問題。

但是我已經嘗試了下面給出的東西,並取得了預期的結果。

exports.getRecommendation=function(req,res){ 
var movieRecommendation = []; 
var id=req.params.id; 
console.log('----- Get User Recommendation - ' + id); 
var url = 'http://52.8.48.113:8080/recommender-server/recommender/v1/recommendations/'+id+'.do'; 
//make http get request 
request({ 
    url: url, 
    json: true 
}, function (error, response, recommendations) { 
     // res.json(recommendations); 

    if (!error && response.statusCode === 200) { 

    console.log('recommendation lenght '+ recommendations.length); 

     // recommendations.forEach(function(entry) { 
     var count=0; 
     async.each(recommendations,function(recommendationItem){ 
      // console.log(recommendationItem); 
      Movie.findOne({'id':parseInt(recommendationItem.itemId)},function(err, movieData){ 
       recommendationItem.movie = movieData; 
       movieRecommendation.push(recommendationItem); 
       count ++; 
       console.log('final res length : ' + movieRecommendation.length); 
       console.log('final res length count : ' + count +' and item recomm lenght ' + recommendations.length); 

      if(count === recommendations.length){ 
       console.log(' =====Final=====> here you can send your response =========' + movieRecommendation.length); 

       res.json(movieRecommendation); 
      } 

      }); 

      // callback(); 

     }); 


    } 


}); 

};

我仍然歡迎任何反饋和建議。

+0

您應該使用傳遞給迭代器函數的'callback',並在'Movie.findOne()'回調中調用它。這樣,'async.each'就會知道每個步驟何時完成。所以,你不需要你使用的所有邏輯。 –

+0

請分享代碼示例。 –

+0

我剛寫了一個答案。看看它是否適合你,請。 –

0

正如我在我的一個評論中提到的,使用傳遞給迭代器函數的callback並在Movie.findOne()回調中調用它。這樣一來,async.each會知道什麼時候每一步驟完成:

async.each(recomendations, function (recomendationItem, callback) { 

    Movie.findOne({'id':parseInt(entry.itemId)},function(err, movieData){ 

     if (err) return callback(err); // if you have an error on you search, just pass it to the iterator callback 

     recommendationItem.movie = movieData; 
     movieRecommendation.push(recommendationItem); 

     callback(); 
    }); 

}, function (error) { 

    if (error) return res.json ({ error: error }); // you should also check if an error ocurred 

    res.json(movieRecomendation); 

}); 

只是想指出:你也可以使用async.eachSeries,這將只是叫你迭代的下一步時,前一個返回(如果該事項給你,但我認爲這不是你的情況),它有相同的簽名。

0

@Vivek潘迪替換下面的代碼你exports.getRecommendation功能內讓你的預期輸出。我們不需要使用計數變量,如果我們使用回調函數。重要的是我們必須使用callback();一次完成所有的過程。我想你已經在你的例子中沒有正確使用回調函數。使用下面的代碼如果有任何問題,請讓我知道。

 var async = require('async'); 
    var request = require("request"); 

     var movieRecommendation = []; 
     var id=req.params.id; 
     console.log('----- Get User Recommendation - ' + id); 
     var url = 'http://52.8.48.113:8080/recommender-server/recommender/v1/recommendations/'+id+'.do'; 

     //make http get request 
     request({ 
      url: url, 
      json: true 
     }, function (error, response, recommendations) { 

      if (!error && response.statusCode === 200) { 

       console.log('recommendation lenght '+ recommendations.length); 

       async.each(recommendations, 

       function(recommendationItem, callback){    

        Movie.findOne({'id':parseInt(recommendationItem.itemId)},function(err, movieData){ 

         recommendationItem.movie = movieData; 
         movieRecommendation.push(recommendationItem); 
         //you have to use callback(); once all your process is done 
         callback(); 

        }); 

       }, 

       function(err){ 
        //you should use this function, this will be execute once all the process done 
        console.log(movieRecommendation); 
        console.log("finally callback"); 
        res.json(movieRecommendation); 

       } 

       ); 

      } 


    });