【问题标题】:MEAN stack: first object pushed into MongoDB schema's array causes RangeErrorMEAN 堆栈:推入 MongoDB 模式数组的第一个对象导致 RangeError
【发布时间】:2017-10-13 17:51:46
【问题描述】:

编辑:我意识到这挂在“res.json(comment);”行我的角度用户界面路线。仍然不知道为什么。

我正在阅读这里的教程:https://thinkster.io/tutorials/mean-stack。这可能与教程有点过时有关。我已将当前状态下的代码上传到http://github.com/orieporter/flappernews

这是一个简单的 reddit 克隆 Web 应用程序,用于发布链接、cmets 并对其进行投票。每次向帖子添加第一条评论时,我都会收到“RangeError:超出最大调用堆栈大小”错误。随后的 cmets 工作没有问题。当我重新启动节点服务器并重新加载页面时,破坏服务器的评论就在那里。谁能帮我在这里找到问题?

完全错误:

events.js:160
  throw er; // Unhandled 'error' event
  RangeError: Maximum call stack size exceeded
at model.Document.$toObject (c:\Users\source\repos\flapper-news\node_modules\mongoose\lib\document.js:1962:24)
at model.Document.toJSON (c:\Users\source\repos\flapper-news\node_modules\mongoose\lib\document.js:2300:15)
at clone (c:\Users\source\repos\flapper-news\node_modules\mongoose\lib\utils.js:252:18)
at cloneArray (c:\Users\source\repos\flapper-news\node_modules\mongoose\lib\utils.js:362:14)
at clone (c:\Users\source\repos\flapper-news\node_modules\mongoose\lib\utils.js:247:12)
at cloneObject (c:\Users\source\repos\flapper-news\node_modules\mongoose\lib\utils.js:343:13)
at clone (c:\Users\source\repos\flapper-news\node_modules\mongoose\lib\utils.js:260:16)
at model.Document.$toObject (c:\Users\source\repos\flapper-news\node_modules\mongoose\lib\document.js:2009:13)
at model.Document.toJSON (c:\Users\source\repos\flapper-news\node_modules\mongoose\lib\document.js:2300:15)
at clone (c:\Users\source\repos\flapper-news\node_modules\mongoose\lib\utils.js:252:18)
at cloneObject (c:\Users\source\repos\flapper-news\node_modules\mongoose\lib\utils.js:343:13)
at clone (c:\Users\source\repos\flapper-news\node_modules\mongoose\lib\utils.js:260:16)
at model.Document.$toObject (c:\Users\source\repos\flapper-news\node_modules\mongoose\lib\document.js:2009:13)
at model.Document.toJSON (c:\Users\source\repos\flapper-news\node_modules\mongoose\lib\document.js:2300:15)
at clone (c:\Users\source\repos\flapper-news\node_modules\mongoose\lib\utils.js:252:18)
at cloneArray (c:\Users\source\repos\flapper-news\node_modules\mongoose\lib\utils.js:362:14)
at clone (c:\Users\source\repos\flapper-news\node_modules\mongoose\lib\utils.js:247:12)

相关 HTML:

<form ng-submit="addComment()" style="margin-top:30px;">
    <h3>Add a new comment</h3>
    <div class="form-group">
        <input type="text" class="form-control" placeholder="Comment" ng-model="body"></input>
    </div>
    <button type="submit" class="btn btn-primary">Post</button>
</form>

角度控制器功能:

$scope.addComment = function () {
    if ($scope.body === '') { return; }
    posts.addComment(post._id, {
        body: $scope.body,
        author: 'user'
    },
    $scope.post);
    $scope.body = '';
};

Angular 工厂函数:

o.addComment = function (id, comment, post) {
    return $http.post('/posts/' + id + '/comments', comment).then(function (response) {
        post.comments.push(response.data);
        return response.data;
    });
};

相关特快路线:

router.post('/posts/:post/comments', function (req, res, next) {
    var comment = new Comment(req.body);
    comment.post = req.post;

    comment.save(function (err, comment) {
        if (err) { return next(err); }

        req.post.comments.push(comment);
        req.post.save(function (err, post) {
            if (err) { return next(err); }

            res.json(comment);
        });
    });
});

评论架构:

var CommentSchema = new mongoose.Schema({
    body: String,
    author: String,
    upvotes: {type: Number, default: 0},
    post: {type: mongoose.Schema.Types.ObjectId, ref: 'Post' }
});

发布架构:

var PostSchema = new mongoose.Schema({
    title: String,
    link: String,
    upvotes: {type: Number, default: 0},
    comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }]
});

【问题讨论】:

  • 评论没有保存在这里:comment.post = req.post; bc 你的请求没有post 属性。它试图以err 的形式回复,但您还没有回复,只是返回了函数。或者您是否有其他路由正在接收next(err) 呼叫?
  • 我从路由文件另一部分的参数中获取帖子。我可以打印 req.post 到控制台没问题,它看起来不错。一旦我将comment.post 设置为req.post,我就无法将我的评论打印到控制台。同样,所有这些仅适用于我在帖子上发表的第一条评论。

标签: javascript angularjs node.js mongodb


【解决方案1】:

我遇到了同样的问题,我花了一些时间(几个有趣的小时!)控制台日志调试、Google 搜索和 thinkster 懒散的头发拉扯试图弄清楚发生了什么。请注意,我对所有这些都是新手,所以我的脑袋围绕着一切可能是最大的挑战。

经过进一步检查,我将原因缩小到 res.json(comment) 行以及创建新评论路由逻辑 (routes/index.js)。

从逻辑上讲,我不明白为什么将整个评论对象推送到 post cmets 数组中,而只需要评论对象 ID。所以很自然地,我最终想通了为什么不直接传递评论对象 id (comment._id) 看看会发生什么。沃拉,它奏效了。没有更多的RangeError: Maximum call stack size exceeded

所以这可能会解决问题,但我好奇的固执的自我想知道为什么这会很重要?为什么它只发生在帖子的第一条评论上,但在其他评论上效果很好?

router.post('/posts/:post/comments', auth, function(req, res, next) {
  var comment = new Comment(req.body);
  comment.post = req.post._id; // <-- originally 'req.post'
  comment.author = req.payload.username;

  comment.save(function(err, comment){
    if(err){ return next(err); }

    req.post.comments.push(comment._id);  // <-- originally 'comment'
    req.post.save(function(err, post) {
      if(err){ return next(err); }

      res.json(comment);
    });
  });
});

我想如果 mongoose 只需要帖子和评论 ID 而不是整个对象,那么为什么不直接保存 ID。存储完整的对象似乎会导致某种无限循环,我相信这会在响应期间导致调用堆栈错误。也许是因为两个对象相互引用?但是话又说回来,我不确定这一切是如何真正起作用的,所以如果那里有任何专家可以阐明,请做。但这应该解决这个问题,并希望对其他人有所帮助。我应该提一下,这是他们提供的实际 Flapper News 代码中的错误。我通过下载他们完整的源代码并运行它发现了这一点。

【讨论】:

  • 感谢 Jashua,这对我有帮助。我认为您绝对正确地认为帖子和评论文档中的循环引用引起的无限循环是正确的。它适用于后续 cmets 的事实让我认为,也许在过去的 mongoose/mongodb 版本中,代码会自动从中获取 ObjectID如果您已定义,则添加的对象是 ObjectID。我想这只是他们的教程过时的另一个例子。我给 Thinkster 发了电子邮件,要求他们更新它,希望他们这样做!
  • 没问题 - 我也给 Thinkster 发过消息。我很高兴我不是唯一遇到此问题的人,并且很高兴找到您的帖子。祝一切顺利。
【解决方案2】:

这是因为res.json(comment); 正在尝试对您在var comment = new Comment(req.body); 上创建的 Comment 对象实例进行字符串化

但是“字符串化”过程显然因为评论对象的大小而挂起(太大,不必进行字符串化)。

你应该用类似的东西替换res.json(comment);

res.json({ status: "success" });

【讨论】:

  • 我在我的其他对象和同一篇文章的后续 cmets 上使用 res.json() 没有问题,它只是导致崩溃的第一个。
猜你喜欢
  • 1970-01-01
  • 2018-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-23
  • 1970-01-01
相关资源
最近更新 更多