javascript - 在模块内部实例化类时超出最大调用堆栈

标签 javascript node.js npm

我在第 7 行的 console.log 打印正常。

主机.js

"use strict";

var engine = require('./engine.js');
var base = require('./base.js');

var player = new base.Avatar();
console.log(player.x);

class PillarGame extends engine.ServerGame {
    connectPlayer(socket) {
        var player = new base.Avatar();
        this.add('players', player);
        console.log("added player");
        //announce
    }   
}

module.exports = {'HostedGame' : PillarGame};

但是在创建该对象并发出后,我的服务器发生了崩溃:

        if (obj.hasOwnProperty(key) && _hasBinary(obj[key])) {
                ^

RangeError: Maximum call stack size exceeded
    at Object.hasOwnProperty (native)

为什么会崩溃?

base.js 没有要求。

堆栈跟踪:

listening
connected
added player
/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:0
(function (exports, require, module, __filename, __dirname) { /*

RangeError: Maximum call stack size exceeded
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:24:22)
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:37:15)
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:47:40)
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:47:40)
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:47:40)
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:37:15)
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:47:40)
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:47:40)
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:47:40)
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:37:15)

server.js,崩溃 socket.emit("game.things", game.things);

var express = require('express');
var path = require('path');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var logic = require('./logic');
var hostedGame = require('./host');

var game = new hostedGame.HostedGame({'sockets' : io.sockets});

app.use(express.static(path.join(__dirname, 'public')));
server.listen(3000, function() {
  console.log('listening');
});


io.on('connection', function(socket) {
  console.log('connected'); //extrac

  game.connectPlayer(socket);

  //console.log("game.things['players']" + game.things['players']);;
  socket.emit("game.things", game.things);

  // socket.on('input', function(data) {
  //   game.input(socket, data);
  // });
});

var loopAsync = function() {
  setTimeout(loop, 10);
  //setImmediate(loop);
}

var now = Date.now();
var last = now;
var dt = 0.00;
var rate = 10;

function loop() {
  now = Date.now();
  var delta = now - last;
  last = now;

  dt = dt + delta;

  if (dt < rate) {
    loopAsync();
    return;
  } else {
    dt -= rate;
    //if dt still > rate, repeat the following while true
    var updates = game.loop();
    //emit things
    io.sockets.emit('player-positions', logic.players);
    //io.to specific player
    loopAsync();
  }

}

loopAsync();

基础.js

"use strict";

class Component {
    defaultMaxCharge() {
        return [0];
    }

    constructor(options) {
        options = options || {};
        this.charge = [0];
        if (options['maxCharge']) {
            this.maxCharge = options['maxCharge'];
        } else {
            this.maxCharge = this.defaultMaxCharge();
        }

    }

    loop() {

    }

    getValue(name, hash) {
        return hash;
    }   
}

class Looper extends Component {
    registrationNames() {
        return ['loop'];
    }
}

class Mover extends Looper {
    loop() {
        var velocity = this.thing.getValue('velocity');
        var speed = this.thing.getValue('speed')['speed'];

        var total = Math.abs(velocity.vx) + Math.abs(velocity.vy);
        if (total <= 0) {
            return;
        }

        var xx = velocity.mx / total * this.speedMod();
        var yy = velocity.my / total * this.speedMod();

        this.thing.x = this.thing.x + xx * speed;
        this.thing.y = this.thing.y + yy * speed;
        this.thing.x += velocity.vx;
        this.thing.y += velocity.vy; //announce
    }
}

//input components

class XWalker extends Component {
    constructor(options) {
        super(options);
        this.vx = 0;
    }

    registrationNames() {
        return ['input', 'velocity'];
    }

    getValue(name, hash) {
        if (name == 'velocity') {
            hash.vx = this.vx; //times speed
        }

        return hash;
    }

    processEvent(name, eventer, hash) {
        if (name == 'input') {
            if (hash.left) {
                this.vx = -1;
            } else if (hash.right) {
                this.vx = 1;
            } else {
                this.vx = 0;
            }
        }
    }
}

class YWalker extends Component {
    constructor(options) {
        super(options);
        this.vx = 0;
    }

    registrationNames() {
        return ['input', 'velocity'];
    }

    getValue(name, hash) {
        if (name == 'velocity') {
            hash.vy = this.vy; //times speed
        }

        return hash;
    }

    processEvent(name, eventer, hash) {
        if (name == 'input') {
            if (hash.up) {
                this.vy = -1;
            } else if (hash.down) {
                this.vy = 1;
            } else {
                this.vy = 0;
            }
        }
    }
}

class Thing {
    spawnComponents(options) {
        return [];
    }

    installComponents(options) {
        this.componentRegistrations = {};
        this.components = [];

        var comps = this.spawnComponents(options);
        for (var i = 0; i < comps.length; i++) {
            var component = comps[i];
            component.thing = this;
            this.registerComponent(component);

            this.components.push(component);
        }
    }

    registerComponent(component) {
        for (var i = 0; i < component.registrationNames().length; i++) {
            var eventName = component.registrationNames()[i];
            if (!this.componentRegistrations[eventName]) {
                this.componentRegistrations[eventName] = [];
            }

            this.componentRegistrations[eventName].push(component);
        }
    }

    getValue(name) {
        var registered = this.componentRegistrations[name];
        if (registered) {
            var valueHash = {};
            for (var i = 0; i < registered.length; i++) {
                var component = registered[i];
                valueHash = component.getValue(name, valueHash);
                if (valueHash.stop) {
                    return valueHash;
                }
            }

            return valueHash;
        }
    }

    processEvent(name, eventer, hash) {
        var registered = this.componentRegistrations[name];
        if (registered) {
            for (var i = 0; i < registered.length; i++) {
                var component = registered[i];
                component.processEvent(name, eventer, hash);
            }
        }
    }

    constructor(options) {
        if (options && options['position']) {
            this.x = options['position'].x * this.canvas.width;
            this.y = options['position'].y * this.canvas.height;
        } else {
            this.x = 2.0;
            this.y = 2.0;   
        }

        this.installComponents(options);
        this.active = true;
    }

    loop() {
        for (var i = 0; i < this.components.length; i++) {
            var component = this.components[i];
            component.loop();
        }
    }   

    afterLoop() {

    }

    position() {
        return {'x' : this.x, 'y' : this.y};
    }
}

class Avatar extends Thing {
    spawnComponents(options) {
        return [new Mover(), new XWalker(), new YWalker()];
    }
}

module.exports = {'Component' : Component, 'Thing' : Thing,
'Mover' : Mover, 'Looper' : Looper, 'XWalker' : XWalker, 'YWalker' : YWalker,
'Avatar' : Avatar};

最佳答案

server.js, crashes on socket.emit("game.things", game.things);

game.things 很可能是一个具有循环引用的复杂对象,socket.io 试图在发出之前将其转换为 JSON,但失败了。

关于javascript - 在模块内部实例化类时超出最大调用堆栈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34278969/

相关文章:

node.js - MongoDB 查询条件和预测

mysql - 尝试在 Node 中批量插入用户数组时出现问题

node.js - Node 包管理器 (NPM) 似乎产生了重复的包

JavaScript:输出符号和特殊字符

JavaScript 数据结构

javascript - Express 4 奇怪的动态中间件行为

react-native - 导入的 createStackNavigator 未定义

reactjs - 部署React前端时如何注入(inject)API服务器URL?

javascript - Angular js $state.go 参数不起作用

c# - 使用谷歌地图的地址验证器