Javascript和Mongoose for循环在执行.find inside之前完成
我和我的搭档需要获得每部电影的平均收视率。电影和评级是我们MongoDB数据库中两个独立的集合 所以,首先我们需要得到所有的电影。在这之后,我们仍然需要在for循环中迭代返回的电影列表的长度。在每次迭代中,我们都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编号
评级。在当前位于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
要解决此问题(有多种方法),请