查询查询的Mongoose异步调用问题

时间:2015-04-29 12:43:13

标签: node.js mongodb mongoose

我有来自Mongo DB的数据填充的var movieRecommendation。问题是Mongoose Movie.findOne()调用asycn调用,这不允许我获取我需要作为响应发回的最终填充movieRecommendation

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 var以使其可用于回复。

4 个答案:

答案 0 :(得分:0)

对于此类问题,我们可以使用http://jsfiddle.net/Panomosh/2cjmggqe/2/库。要在完成所有操作后最终填充数据,我们可以使用异步库中的 async.each 集合。

例如: 注意:通过此命令安装Async      npm install async 以使用异步库

    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。一旦为迭代执行了所有操作,您应该使用 callback()

答案 1 :(得分: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,只会在前一个回复时调用迭代的下一步(如果这对你很重要,但我认为这不是你的情况)并且它具有相同的签名。

答案 2 :(得分:0)

@Vivek Panday 替换 exports.getRecommendation函数中的以下代码以获得预期的输出。如果我们使用回调函数,我们不需要使用 count 变量。重要的是我们必须在完成所有过程后使用 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);

                }

                );

          }


    });

答案 3 :(得分:-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();

        });


    }


});

};

我仍然愿意接受任何反馈和建议。