mongodb RangeError:最大调用堆栈大小超过

时间:2018-01-20 10:14:09

标签: node.js mongodb

MongoDB版本:2.6.10,节点v6.12.1。 ,Ubuntu 16.04.3

我有一个在MongoDB中生成对象的代码,当我在本地运行它时,代码工作得很好(流浪汉机器),但是当我在AWS服务器上运行它时会抛出以下错误 - 但仅针对非常具体的情况:

  1. 创建一个Outlet对象,
  2. 首次创建与Outlet关联的远程对象**
  3. 注意:

    1. 如果我不是第一次为Outlet创建Remote,则不会抛出错误。

    2. 远程对象是在数据库中创建的,但是节点进程终止并由Forever服务重新启动(导致UI中断)。

    3. 记录错误消息:

      RangeError: Maximum call stack size exceeded
          at Function.isValid (/data1/slmusic/mean/node_modules/mongodb-core/node_modules/bson/lib/bson/objectid.js:313:36)
          at new ObjectID (/data1/slmusic/mean/node_modules/mongodb-core/node_modules/bson/lib/bson/objectid.js:46:24)
          at clone (/data1/slmusic/mean/node_modules/mongoose/lib/utils.js:272:12)
          at cloneObject (/data1/slmusic/mean/node_modules/mongoose/lib/utils.js:343:13)
          at clone (/data1/slmusic/mean/node_modules/mongoose/lib/utils.js:260:16)
          at model.Document.$toObject (/data1/slmusic/mean/node_modules/mongoose/lib/document.js:2073:13)
          at model.Document.toJSON (/data1/slmusic/mean/node_modules/mongoose/lib/document.js:2364:15)
          at clone (/data1/slmusic/mean/node_modules/mongoose/lib/utils.js:252:18)
          at cloneArray (/data1/slmusic/mean/node_modules/mongoose/lib/utils.js:362:14)
          at clone (/data1/slmusic/mean/node_modules/mongoose/lib/utils.js:247:12)
          at cloneObject (/data1/slmusic/mean/node_modules/mongoose/lib/utils.js:343:13)
          at clone (/data1/slmusic/mean/node_modules/mongoose/lib/utils.js:260:16)
          at model.Document.$toObject (/data1/slmusic/mean/node_modules/mongoose/lib/document.js:2073:13)
          at model.Document.toJSON (/data1/slmusic/mean/node_modules/mongoose/lib/document.js:2364:15)
          at clone (/data1/slmusic/mean/node_modules/mongoose/lib/utils.js:252:18)
          at cloneObject (/data1/slmusic/mean/node_modules/mongoose/lib/utils.js:343:13)
      

      代码:

      用于创建Remote的后端文件(create方法中的相关代码)

      import * as Remote from "../models/Remote";
      import * as Outlet from "../models/Outlet";
      import * as Playlist from "../models/Playlist";
      import * as Organization from "../models/Organization";
      
      
      class RemoteRoutes {
      
         ....
      
          create(req: any, res: any, next: any) {
              Outlet.findById(req.body.oId, function (err: any, outlet: any) {
                  if (err) {
                      return next(err);
                  }
                  var remoteData = req.body;
                  delete remoteData.oId;
                  remoteData.outlet = outlet;
                  Remote.create(remoteData, function (err: any, remote: any) {
                      if (err) {
                          return next(err);
                      }
                      outlet.remotes.push(remote);
                      outlet.save(function (err: any) {
                          res.json({
                              type: true,
                              data: remote,
                          });
                      });
                  });
      
              });
          }
      
          ...
      }
      
      var remoteRoute: RemoteRoutes = new RemoteRoutes();
      
      export = remoteRoute;
      

      用于创建远程

      的前端文件
      define('js/controllers/addRemoteCtrl', [], function() {
      
        function addRemoteCtrl($scope, $routeParams, Remotes, Outlets, loginSrv, auth, $location, alertServ, loaderServ, validationServ) {
          // console.log('$routeParams ', $routeParams);
          auth.verify();
          $scope.outlet = Outlets.get({
            id: $routeParams.oId
          });
      
      
          function handleRequest(res) {
            if (res.type) {
              loaderServ.hide();
      
              $location.url('/remotes/' + $routeParams.oId);
            } else {
              // console.log('res.data ' , res.data);
              // alert(res.data);
              alertServ.add('danger', res.data);
      
            }
          }
      
          $scope.addRemote = function() {
      
            var remote = new Remotes({
              name: $scope.name,
              email: $scope.email,
              oId: $routeParams.oId,
            });
      
            if (validationServ.validateRemote(remote)) {
              loaderServ.show();
              remote.$save(handleRequest);
            }
          }
      
      
        };
      
        addRemoteCtrl.$inject = ['$scope', '$routeParams', 'Remotes', 'Outlets', 'loginSrv', 'auth', '$location', 'alertServ', 'loaderServ', 'validationServ'];
      
      
        return addRemoteCtrl;
      });
      

      远程架构IRemote.ts:

      import IOutlet = require("./IOutlet");
      
      
      interface IRemote {
          name: string;
          email: string;
          outlet: IOutlet;
      
      };
      
      export = IRemote;
      

      Remote Schema Remote.ts:

      import * as mongoose from "mongoose";
      import IRemote = require("./IRemote");
      
      
      
      
      interface IRemoteModel extends IRemote, mongoose.Document { }
      
      var remoteSchema = new mongoose.Schema({
          name: String,
          email: String,
          outlet: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'Outlet' }
      
      });
      
      var remote = mongoose.model<IRemoteModel>("Remote", remoteSchema);
      
      export = remote;
      

1 个答案:

答案 0 :(得分:0)

正如Saravana所提到的,这是由循环引用引起的,可以解决如下:

使用以下代码获取遥控器(在RemotesCtrl.js中):

$scope.getRemotes = function() {
  res = $http.get(API + '/outlet/remotes/' + $routeParams.id);
  res.then(function(res) {
    loaderServ.hide();

    $scope.remotes = res.data;
  });
  return res;
};

$scope.getRemotes();

并在remoteRoute.js中注释以下几行

create(req: any, res: any, next: any) {
    Outlet.findById(req.body.oId, function (err: any, outlet: any) {
        if (err) {
            return next(err);
        }
        var remoteData = req.body;
        delete remoteData.oId;
        remoteData.outlet = outlet;
        Remote.create(remoteData, function (err: any, remote: any) {
            if (err) {
                return next(err);
            }
            // outlet.remotes.push(remote);
            // outlet.save(function (err: any) {
                res.json({
                    type: true,
                    data: remote,
                });
            // });
        });

    });
}

以下是后端getRemote()的代码:

  getRemotes(req: any, res: any, next: any) {
    Remote.find({outlet: req.params.id}, function (err: any, post: any) {
        if (err) {
            return next(err);
        }
        res.json(post);
    });
  }