Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript和Mongoose for循环在执行.find inside之前完成_Javascript_Node.js_Mongodb_Express - Fatal编程技术网

Javascript和Mongoose for循环在执行.find inside之前完成

Javascript和Mongoose for循环在执行.find inside之前完成,javascript,node.js,mongodb,express,Javascript,Node.js,Mongodb,Express,我和我的搭档需要获得每部电影的平均收视率。电影和评级是我们MongoDB数据库中两个独立的集合 所以,首先我们需要得到所有的电影。在这之后,我们仍然需要在for循环中迭代返回的电影列表的长度。在每次迭代中,我们都评级。在当前位于for循环索引中的电影的tt\u编号上查找。在这一点上,它应该计算该电影所有收视率的平均值,并将结果存储在字符串JSON中。每部电影都是这样 然而,我在这里包含的代码并不是这样的。相反,for循环首先完成,然后执行Rating.find三次,最后一次迭代电影的tt\u编号

我和我的搭档需要获得每部电影的平均收视率。电影和评级是我们MongoDB数据库中两个独立的集合

所以,首先我们需要得到所有的电影。在这之后,我们仍然需要在for循环中迭代返回的电影列表的长度。在每次迭代中,我们都
评级。在当前位于for循环索引中的电影的
tt\u编号上查找
。在这一点上,它应该计算该电影所有收视率的平均值,并将结果存储在字符串JSON中。每部电影都是这样

然而,我在这里包含的代码并不是这样的。相反,for循环首先完成,然后执行Rating.find三次,最后一次迭代电影的
tt\u编号除外

var express = require('express');
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/Notflix', {useMongoClient: true});
var Movie = require('../model/movies.js');
var Rating = require('../model/ratings.js');
var jwt = require('jsonwebtoken');
var router = express.Router();

router.get('/', function (req, res) {
var jsonString = '{"The average ratings":[]}';
var obj = JSON.parse(jsonString);
var moviett_number;

Movie.find({}, function (err, movies) {
    if (err) {
        res.status(500);
        res.json({errorMessage: '500 SERVER-SIDE ERROR - No list of movies to get the average ratings of could be found.'});
    }

    for (var i = 0; i < movies.length; i++) {
        //TODO: I THINK THIS FOR LOOP IS COMPLETED FULLY BEFORE FINALLY THE RATING.FIND IS DONE???????
        //Go through the list of all movies, getting the ratings for each...
        moviett_number = movies[i].tt_number;

        console.log(i + " - " + moviett_number);

        Rating.find({'tt_number': moviett_number}, function (err, movieRatings) {
            //Get all the ratings for the current movie...

            if (err) {
                res.status(500);
                res.json({errorMessage: '500 SERVER-SIDE ERROR - No list of average ratings for this movie could be found.'});
                return;
            }

            if (movieRatings > 0) {
                //If it has ratings, calculate the average rating.
                var amountOfRatings;
                var average = 0;

                for (amountOfRatings = 0; amountOfRatings < movieRatings.length; amountOfRatings++) {
                    average += parseInt(movieRatings[amountOfRatings].rating);
                }

                average = Math.round((average / amountOfRatings) * 100) / 100;

                //Add the average rating for this movie to the response jsonString.
                obj["The average ratings"].push({
                    averageRatingMessage: 'Movie with tt_number = [' + moviett_number + '] has the following average rating.',
                    averageRating: average
                });
            } else {
                //Add a notice that this movie does not have any ratings and therefore no average rating either to the response jsonString.
                obj["The average ratings"].push({noRatingMessage: 'Movie with tt_number = [' + moviett_number + "] has no ratings yet."});
            }

            //TODO: WATCH FOR THIS CONSOLE.LOG, IT SHOWS A WEIRD ISSUE.
            console.log(obj);
        });
    }

    jsonString = JSON.stringify(obj);

    //TODO: ASYNCHRONOUS ISSUE, RESPONSE IS SET BEFORE THE CODE ABOVE IS DONE, BECAUSE THE PROGRAM CONTINUES EVEN IF THE FOR LOOP ISN'T DONE YET!
    console.log(jsonString);

    res.status(200);
    res.json(jsonString);
});
});
更新 这个问题与前面提到的其他问题不同,因为这个问题涉及响应生成器和动态响应内容。其他的是关于如何处理循环和任务的一般性说明,这些循环和任务是在其他循环和任务之前完成的。它们与我要查找的内容非常接近,但我在连续两个小时的查找过程中也没有找到它们,而且它们几乎错过了我要查找的内容。

Model.find()
方法是异步的,因此在从数据库返回结果之前发送结果。获取所有数据后,需要使用回调来实际发送响应

// callback when all your Rating.find() are complete
function done(movies) {
  res.json(movies);
}

// get the movies
Movie.find({}, function (err, movies) {
  // loop over the results
  movies.forEach(function(movie, i) {
    // get the Rating for this Movie
    Rating.find({'tt_number': movie.tt_number}, function (err, ratings) {
      // add the rating
      movie.rating = ratings.reduce(function(total, rating) {
        total += rating;
        return total;
      }, 0) / ratings.length;

      // this is the last one, call done()
      if (movies.length-1 === i) {
        done(movies);
      }
    });
  }
});
Model.find()
方法是异步的,因此在从数据库返回结果之前发送结果。获取所有数据后,需要使用回调来实际发送响应

// callback when all your Rating.find() are complete
function done(movies) {
  res.json(movies);
}

// get the movies
Movie.find({}, function (err, movies) {
  // loop over the results
  movies.forEach(function(movie, i) {
    // get the Rating for this Movie
    Rating.find({'tt_number': movie.tt_number}, function (err, ratings) {
      // add the rating
      movie.rating = ratings.reduce(function(total, rating) {
        total += rating;
        return total;
      }, 0) / ratings.length;

      // this is the last one, call done()
      if (movies.length-1 === i) {
        done(movies);
      }
    });
  }
});

这是因为Node.js的工作方式。它首先执行for循环,并看到要执行的Rating.find,但由于Node.js不能同时执行两件事情(并且它已经忙于for循环),它将Rating.find添加到a堆栈中,以便稍后执行(当Node.js空闲时),这种情况会发生3次,因为您有3部电影。当for循环完成后,Node.js可以自由地执行Rating.find,但是现在i的值(来自for循环)已经是3,这就是为什么它总是插入最后一个Rating

要解决此问题(有多种方法),可以在IIFE(中间调用的函数表达式)中解决Rating.find。检查以下内容:

var express = require('express');
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/Notflix', {useMongoClient: true});
var Movie = require('../model/movies.js');
var Rating = require('../model/ratings.js');
var jwt = require('jsonwebtoken');
var router = express.Router();

router.get('/', function (req, res) {
var jsonString = '{"The average ratings":[]}';
var obj = JSON.parse(jsonString);
var moviett_number;

Movie.find({}, function (err, movies) {
    if (err) {
        res.status(500);
        res.json({errorMessage: '500 SERVER-SIDE ERROR - No list of movies to get the average ratings of could be found.'});
    }

    for (var i = 0; i < movies.length; i++) {
        //TODO: I THINK THIS FOR LOOP IS COMPLETED FULLY BEFORE FINALLY THE RATING.FIND IS DONE???????
        //Go through the list of all movies, getting the ratings for each...
        moviett_number = movies[i].tt_number;

        console.log(i + " - " + moviett_number);

                (function() {
          Rating.find({'tt_number': moviett_number}, function (err, movieRatings) {
              //Get all the ratings for the current movie...

              if (err) {
                  res.status(500);
                  res.json({errorMessage: '500 SERVER-SIDE ERROR - No list of average ratings for this movie could be found.'});
                  return;
              }

              if (movieRatings > 0) {
                  //If it has ratings, calculate the average rating.
                  var amountOfRatings;
                  var average = 0;

                  for (amountOfRatings = 0; amountOfRatings < movieRatings.length; amountOfRatings++) {
                      average += parseInt(movieRatings[amountOfRatings].rating);
                  }

                  average = Math.round((average / amountOfRatings) * 100) / 100;

                  //Add the average rating for this movie to the response jsonString.
                  obj["The average ratings"].push({
                      averageRatingMessage: 'Movie with tt_number = [' + moviett_number + '] has the following average rating.',
                      averageRating: average
                  });
              } else {
                  //Add a notice that this movie does not have any ratings and therefore no average rating either to the response jsonString.
                  obj["The average ratings"].push({noRatingMessage: 'Movie with tt_number = [' + moviett_number + "] has no ratings yet."});
              }

              //TODO: WATCH FOR THIS CONSOLE.LOG, IT SHOWS A WEIRD ISSUE.
              console.log(obj);
          });
        })();
    }

    jsonString = JSON.stringify(obj);

    //TODO: ASYNCHRONOUS ISSUE, RESPONSE IS SET BEFORE THE CODE ABOVE IS DONE, BECAUSE THE PROGRAM CONTINUES EVEN IF THE FOR LOOP ISN'T DONE YET!
    console.log(jsonString);

    res.status(200);
    res.json(jsonString);
});
var express=require('express');
var mongoose=require('mongoose');
猫鼬mongodb://localhost/Notflix“,{useMongoClient:true});
var Movie=require('../model/movies.js');
var Rating=require('../model/ratings.js');
var jwt=require('jsonwebtoken');
var router=express.router();
router.get('/',函数(req,res){
var jsonString='{“平均评级”:[]}';
var obj=JSON.parse(jsonString);
var moviett_编号;
Movie.find({},函数(呃,movies){
如果(错误){
物质状态(500);
res.json({errorMessage:'500服务器端错误-找不到可获得平均收视率的电影列表。');
}
for(var i=0;i0){
//如果有评级,则计算平均评级。
var Amountotings;
var平均值=0;
对于(amountFratings=0;amountFratings
这是因为Node.js的工作方式。它首先执行for循环,然后看到要执行的Rating.find,但由于Node.js不能同时执行两件事情(并且它已经忙于for循环),因此它将Rating.find添加到a堆栈中,以便稍后执行(当Node.js空闲时),在您的案例中会发生3次,因为您有3部电影。当for循环完成后,Node.js可以自由执行Rating.find,但现在i(来自for循环)的值已经是3,这就是为什么它总是插入最后一个Rating

要解决此问题(有多种方法),请