nodejs:继承EventEmitter

时间:2016-01-23 17:07:11

标签: javascript node.js inheritance

我无法创建一个继承自EventEmitter的类。 emit()函数最终未定义。这是问题的简化摘录:

var EventEmitter = require( 'events' );
var util = require( 'util' );
var zWave = require('./zWaveRequest.js');
var CronJobManager = require( 'cron-job-manager' );
var timespanToCron = require( './parseTime.js' ).timespanToCron;
var winston = require( './logger.js' );

const levelCronName = 'level';

var Switch = function (id, displayName, onTime, offTime) {
    var _nodeNum;
    var _nodeName;
    var _lastLevel = -1;
    var _levelPollInterval = config.levelPollInterval;
    var _levelTS = 0;
    var _cronMgr = new CronJobManager( );

    EventEmitter.call( this );

    var self = this;

    function initLevelJob() {
        // the log shows self.emit() doesn't exist (???)
        if( typeof self.emit === 'function' ) winston.info( 'initLevelJob(): self.emit() is defined' );
        else winston.info( 'initLevelJob(): self.emit() is NOT defined' );

        _cronMgr.add( levelCronName, timespanToCron( _levelPollInterval ), function() {
            self.getLevel();
        }, 
        {
            start: true,
        } );
    }

    this.getLevel = function() {
        zWave.curLevel( _nodeNum )
        .then( function( value ) {
            _lastLevel = value;
            _levelTS = Date.now( );

            // this next call always fails with an 'emit is not a function' error
            self.emit( 'level', self.lastLevel, self.lastLevelTS );
        } );
    }

    Object.defineProperties(this, {
        nodeNumber: {
            get: function() { return _nodeNum; },
            set: function( val ) {
                _nodeNum = val;
                initLevelJob( );
            },
        },

        levelPollInterval: {
            get: function() { return _levelPollInterval; },
            set: function( val ) {
                _levelPollInterval = val;
                initLevelJob( );
            }
        },
}

util.inherits( Switch, EventEmitter );

module.exports = Switch;

这里的总体思路是设置一个cronjob来ping另一台服务器以获取信息(这是对zWave的调用)。 cronjob回调更新了一些内部变量,然后发出一个事件。

但self.emit()未定义,即使我认为我正在遵循如何从EventEmitter继承的示例。

致电代码

从我现在尝试使用emit()的角度来看,在Switch对象之外没有任何事情发生。换句话说,我还没有任何事件监听器与Switch绑定。

这里是我如何创建Switch的实例(SunsetSwitch派生自Switch):

function createSwitch( switchFile ) {
    var raw = JSON.parse( fs.readFileSync( switchFile ) );
    var retVal;

    if( typeof raw.onTime === 'undefined' ) {
        // sunset switch
        retVal = new SunsetSwitch( );

        if( config.forceImmediateOn ) {
            var now = new Date( );

            var sunset = sunCalc.getTimes( now, config.latitude, config.longitude ).sunset;
            retVal.onOffset = Math.ceil( ( now - sunset ) / 60000 ) - 5;

            var turnOff = new Date( now );
            turnOff.setMinutes( now.getMinutes( ) + config.testMode.duration.totalMinutes() );
            retVal.offTime = turnOff;

            retVal.basedOnSunrise = raw.basedOnSunrise;
        }
        else {
            retVal.onOffset = raw.onOffset;
            retVal.offTime = raw.offTime;
            retVal.basedOnSunrise = raw.basedOnSunrise;
        }
    }
    else {
        // regular switch
        retVal = new Switch( );

        retVal.offTime = raw.offTime;
        retVal.onTime = raw.onTime;
    }

    if( config.forceImmediateOn ) retVal.ignoreInitialOff = false;
    else {
        if( typeof raw.ignoreInitial != 'boolean' ) retVal.ignoreInitialOff = true;
        else retVal.ignoreInitialOff = raw.ignoreInitialOff;
    }

    retVal.displayName = raw.displayName;
    retVal.nodeName = raw.nodeName;
    retVal.nodeNumber = raw.nodeNumber;

    return retVal;
}

从文件系统循环中调用createSwitch(),该循环读取一堆json文件:

fs.readdirSync('./switches')
.filter(function (file) {
    return file.substr(-5) === '.json';
})
.forEach(function (file) {
    switches.push(createSwitch('./switches/' + file));
});

这是我目前收到的错误消息:

  

未处理拒绝TypeError:self.emit不是函数       在/home/mark/XmasLights/switch.js:65:18       在tryCatcher(/home/mark/XmasLights/node_modules/bluebird/js/release/util.js:11:23)       在Promise._settlePromiseFromHandler(/home/mark/XmasLights/node_modules/bluebird/js/release/promise.js:488:31)       在Promise._settlePromise(/home/mark/XmasLights/node_modules/bluebird/js/release/promise.js:545:18)       在Promise._settlePromise0(/home/mark/XmasLights/node_modules/bluebird/js/release/promise.js:590:10)       在Promise._settlePromises(/home/mark/XmasLights/node_modules/bluebird/js/release/promise.js:673:18)       at Async._drainQueue(/home/mark/XmasLights/node_modules/bluebird/js/release/async.js:125:16)       at Async._drainQueues(/home/mark/XmasLights/node_modules/bluebird/js/release/async.js:135:10)       在Immediate.Async.drainQueues [as _onImmediate](/home/mark/XmasLights/node_modules/bluebird/js/release/async.js:16:14)       at processImmediate [as _immediateCallback](timers.js:383:17)

以下是如何定义SunsetSwitch的摘录:

var Switch = require('./switch.js');

var SunsetSwitch = function (id, displayName, onOffset, offTime) {
    Switch.call(this, id, displayName, null, offTime);
}

module.exports = SunsetSwitch;

1 个答案:

答案 0 :(得分:1)

感谢所有回复的人,尤其是jfriend00,他让我走上了解决方案的道路。

问题源于我在定义SunsetSwitch时所做的事情,这是从Switch派生的。

我忽略了将此行包含在SunsetSwitch的模块文件中:

util.inherits( SunsetSwitch, Switch );

基于我对javascript的有限理解,这个遗漏阻止了Switch的原型传播到SunsetSwitch。

我需要记住,在javascript中定义继承树并不像C#那样简单,例如,C#,我有大部分的经验。你必须设置属性--Switch.call(this,id,displayName,null,offTime) - 并复制原型 - util.inherits(SunsetSwitch,Switch)。