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

标签 javascript node.js mongodb express

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

所以,首先我们需要获取所有电影。之后,我们仍然需要在 for 循环中迭代返回的电影列表的长度。在每次迭代中,我们对当前位于 for 循环索引上的电影的 Rating.find 进行 tt_number 。此时,它应该计算该电影所有评分的平均值并将结果存储在字符串 JSON 中。每部电影都会这样做。

但是,我在此处包含的代码没有执行类似的操作。相反,for 循环首先完成,然后执行三次 Rating.find,每次都使用最后一次迭代电影的 tt_number

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);
});
});

输出:

0 - 123
1 - 456
2 - 789

{"The average ratings":[]}

{ 'The average ratings': [ { noRatingMessage: 'Movie with tt_number = [789] has no ratings yet.' } ] }

{ 'The average ratings': 
   [ { noRatingMessage: 'Movie with tt_number = [789] has no ratings yet.' },
     { noRatingMessage: 'Movie with tt_number = [789] has no ratings yet.' } ] }

{ 'The average ratings': 
   [ { noRatingMessage: 'Movie with tt_number = [789] has no ratings yet.' },
     { noRatingMessage: 'Movie with tt_number = [789] has no ratings yet.' },
     { noRatingMessage: 'Movie with tt_number = [789] has no ratings yet.' } ] }

更新

此问题与其他问题不同,因为此问题涉及响应生成器和动态响应内容。其他的一般是关于如何处理 for 循环和在其他之前完成的任务。它们很接近我要找的东西,但我在连续寻找 2 个小时的时候也没有找到它们,而且它们几乎没有找到我要找的东西。

最佳答案

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);
      }
    });
  }
});

关于Javascript 和 Mongoose for 循环在执行内部 .find 之前完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46737664/

相关文章:

javascript - Expressjs 如何决定调用哪个错误处理程序。如果我们有多个错误句柄

node.js - 错误 : no open connections at Db. _executeQueryCommand Node.js

node.js - 加载资源失败:net::ERR_INSECURE_RESPONSE socket.io

mongodb - 意外的 mongo 退出代码 100。正在重新启动

c# - 将 UpdateDefinition<TEntity> 用于 MongoDB 通用存储库

javascript - 我们可以使用 JavaScript 从网页中获取数据吗?

javascript - ExtJS 中的自定义类属性

Javascript:摆脱动画 SCSS - 当侧边栏在折叠后打开时

javascript - 在卸载时或卸载前确认时发送 SocketIO 消息

node.js - 在 Nodejs Express 中实现单元测试 - 意外失败