2016-01-23 106 views
0

我無法創建從EventEmitter繼承的類。 emit()函數最終未定義。這裏的問題的簡化提取物:nodejs:inheriting EventEmitter

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中。

下面是我如何創建開關的情況下(SunsetSwitch從交換機導出):

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

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文件名爲

以下是我目前收到的錯誤消息:

Unhandled rejection TypeError: self.emit is not a function at /home/mark/XmasLights/switch.js:65:18 at tryCatcher (/home/mark/XmasLights/node_modules/bluebird/js/release/util.js:11:23) at Promise._settlePromiseFromHandler (/home/mark/XmasLights/node_modules/bluebird/js/release/promise.js:488:31) at Promise._settlePromise (/home/mark/XmasLights/node_modules/bluebird/js/release/promise.js:545:18) at Promise._settlePromise0 (/home/mark/XmasLights/node_modules/bluebird/js/release/promise.js:590:10) at 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) at 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)

這裏是h ow一個SunsetSwitch被定義爲:

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

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

module.exports = SunsetSwitch; 
+0

是否在構造函數中定義了'this.emit'? – Bergi

+0

您使用的是什麼版本的節點? – mscdex

+1

另外,在實例化時使用'new Switch()'還是'Switch()'? – mscdex

回答

1

感謝所有回覆的人,特別是jfriend00,他讓我走上了解決問題的道路。

這個問題源於我在定義從Switch派生的SunsetSwitch時沒有做的事情。

我忘了把模塊文件這一行SunsetSwitch:

util.inherits(SunsetSwitch, Switch); 

根據我有限的JavaScript的理解,即遺漏開關防止原型傳播到SunsetSwitch。

我需要記住的是,在JavaScript中定義繼承樹並不像在C#中那樣簡單,例如我擁有大部分經驗。您必須同時設置屬性--Switch.call(this,id,displayName,null,offTime) - 並複製原型 - util.inherits(SunsetSwitch,Switch)。