【问题标题】:Nodejs RangeError: Maximum call stack size exceeded, caused by sending object in responseNodejs RangeError:超出最大调用堆栈大小,由响应中发送对象引起
【发布时间】:2016-07-14 02:02:52
【问题描述】:

如果有人能帮我解决这个问题,那就太好了。

我目前遇到了一个问题,调用此快速路由会在 RangeError 下方显示错误:超出最大调用堆栈大小

它似乎只在我包含 res.json(users[user]); 时发生功能。如果我用 res.send('Done'); 代替这个函数该功能运行良好。

我试过 setTimeout、setImmediate 和 process.nextTick,都给我同样的错误,差不多。

我有点希望这是我的一个愚蠢的错误。

//Send Friend Request
router.post('/send/friend/request', auth, function(req, res, next){

 var query = User.find({$or: [
  {username: req.body.username},
  {username: req.payload.username}
 ]})
 .select(' username friends notifications');

 query.exec(function(err, users){
  if(err) return next(err);
  if(users.length < 2) console.log('/send/friend/request - There was an error      in accessing the users from the db');
  else{

   //Identify users in array
   var user = users.findIndex(function(element, index){
    if(element.username === req.payload.username)
      return element;
    });
   var requestUser = (user + 1) % 2;

   //addFriends
   users[user].friends.push({
     user: users[requestUser],
   });

   users[requestUser].friends.push({
     user: users[user],
     sent: false
   });

   //notifications
   users[user].notifications.push({ 
     user: users[requestUser],  
     type: 0, 
     summary: "Your friend request has been sent to " + req.body.username +".",
     status: "Pending..."
   });

   users[requestUser].notifications.push({
     user: users[user],  
     type: 1, 
     summary: "You have a new friend request from " + req.payload.username + ".",
     status: "Pending..."
   });

   users[requestUser].save(function(err){
     if(err) return next(err);
   });

   users[user].save(function(err){
    if(err) return next(err);
   });

     //Here lies the culprit
     res.json(users[user]);
  }
 });
});

【问题讨论】:

    标签: node.js express


    【解决方案1】:

    您正在创建users[user]users[requestUser] 之间的循环引用。

    这是一个演示问题的示例:

    const mongoose = require('mongoose');
    const Schema   = mongoose.Schema;
    
    const userSchema = Schema({ friends : [] });
    const User       = mongoose.model('User', userSchema);
    
    let user1 = new User();
    let user2 = new User();
    
    user1.friends.push(user2); 
    user2.friends.push(user1); // the circular reference is created here
    
    console.log( JSON.stringify(user1) );
    

    JSON.stringify() 会因为循环引用而抛出 RangeError

    您可能需要重新考虑您的架构,因为我认为您不能将subdocs 用于您的目的。相反,您应该使用"population" 来存储文档之间的引用。

    当您将上面的架构更改为以下时,它不会抛出:

    const userSchema = Schema({
      friends : [ { type : Schema.Types.ObjectId, ref : 'User' } ]
    });
    

    编辑:如果您使用复杂对象作为数组内容,即使有人口,您也应该推送_id 值而不是文档:

    users[user].friends.push({
      user: users[requestUser]._id,
    });
    

    【讨论】:

    • 这是我目前在我的用户架构中的好友好友:[{ user: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },friendRequest: { type: Boolean , 默认: true}, 发送: { type: Boolean , default: true}, 接受: { type: Boolean , default: false} }],我不确定这是不是问题。
    • @MatrixEntry1337 在这种情况下,您可能必须使用.push({ user: users[requestUser]._id })
    【解决方案2】:

    也许

    如果 user 本身包含引用,则 res.json 失败。因为req.json 试图爆炸unlimited 对象。为避免此问题,您可以:

    1. 指定要发送的用户字段

      res.send(JSON.stringify(user, ['name', 'age', ...]))

    2. 将引用定义为不可枚举的属性

      Object.defineProperty(user, 'your-ref', {enumerable: false});

    【讨论】:

    • 是的!正如你所说, res.json 试图爆炸无限对象。我指定了除用户 ref 之外的所有其他字段,它解决了问题。谢谢!
    【解决方案3】:

    对象 users 肯定不是 JSON。它的 POJO 对象带有额外的 mongo 属性,其中包含对 __proto__ 属性的递归引用。

    进行序列化,然后在客户端再次反序列化。

    或者在新的 Object 字面量中提取属性然后传递给它resp.json()

    【讨论】:

      猜你喜欢
      • 2019-07-05
      • 2014-02-07
      • 1970-01-01
      • 2013-08-18
      • 2015-06-28
      • 2018-02-06
      • 2018-06-26
      相关资源
      最近更新 更多