首页 文章

nodejs:继承EventEmitter

提问于
浏览
0

我无法创建继承自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继承的示例 .

Calling Code

从我现在如何尝试使用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在tryCatcher的/home/mark/XmasLights/switch.js:65:18不是函数(/home/mark/XmasLights/node_modules/bluebird/js/release/util.js:11 :23)Promise._settleFromHandler(/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)在Async._drainQueue(/home/mark/XmasLights/node_modules/bluebird/js/release/async.js:125:16)的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 回答

  • 1

    对所有回应的人,特别是对jfriend00的人来说,他让我走上了解决之道 .

    这个问题源于我在定义SunsetSwitch时没有做的事情,它是从Switch派生的 .

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

    util.inherits( SunsetSwitch, Switch );
    

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

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

相关问题