2016-08-30 1 views
0

я получаю эту ошибку в своем кодеЯ только начал изучать node.js, и я реализовал демонстрационный код, демонстрирующий прослушиватели событий. Я получил сообщение об ошибке

TypeError: account.on() is not a function

Где я ошибся?

Код

var events = require('events'); 

function Account() { 

    this.balance = 0; 

    events.EventEmitter.call(this); 

    this.deposit = function(amount) { 
    this.balance += amount; 
    this.emit('balanceChanged'); 
    }; 

    this.withdraw = function(amount) { 
    this.balance -= amount; 
    this.emit('balanceChanged'); 
    }; 
} 

Account.prototype._proto_ = events.EventEmitter.prototype; 

function displayBalance() { 
    console.log('Account balance : $%d', this.balance); 
} 

function checkOverdraw() { 
    if (this.balance < 0) { 
    console.log('Account overdrawn!!!'); 
    } 
} 

function checkgoal(acc, goal) { 
    if (acc.balance > goal) { 
    console.log('Goal Achieved!!!'); 
    } 
} 


var account = new Account(); 

account.on('balanceChanged', displayBalance); 

account.on('balanceChanged', checkOverdraw); 

account.on('balanceChanged', function() { 
    checkgoal(this, 1000); 
}); 


account.deposit(220); 
account.deposit(320); 
account.deposit(600); 
account.withdraw(1200); 
+1

http://stackoverflow.com/documentation/node.js/1623/event-emitters/5254/basics#t=201608300859206033451 или вы можете использовать 'function Account (...) {...}; util.inherits (Acount, require ('events')); ' –

+0

Я думаю * proto * в' Account.prototype.proto = events.EventEmitter.prototype; ', должен быть' __proto__': 'Account.prototype .__ proto __ = events.EventEmitter.prototype; '. Конечно, @AikonMogwai заявлял, что проще использовать * util.inherits * в узле для наследования. – dNitro

ответ

1

Ваш пример кода не идиоматическое Node JS.

я настоятельно рекомендую вам следовать рекомендациям лучших практик при создании новых наследуемых объектов, как:

var util=require('util'); 
var EventEmitter = require('events').EventEmitter; 

var Account = function(){ 
    EventEmitter.call(this); // should be first 
    this.balance=0; // instance var 
}; 
util.inherits(Account,EventEmitter); 

Account.prototype.deposit = function(amount){ 
    this.balance += amount; 
    this.emit('balanceChanged'); 
}; 

Account.prototype.withdraw = function(amount){ 
    this.balance -= amount; 
    this.emit('balanceChanged'); 
}; 

var account = new Account(); 

var displayBalance = function(){ 
    console.log("Account balance : $%d", this.balance); 
}; 

account.on('balanceChanged',displayBalance); 

account.deposit(200); 
account.withdraw(40); 

// ... etc. .... 

, при выполнении которой отображается:

Account balance : $200 
Account balance : $160 

Лучшие практики там так, что

  1. Ваш код может быть выражен таким образом, чтобы его было легко понять
  2. вы не сталкиваетесь с неожиданными проблемами при попытке реплицировать уже определенные функциональные возможности, возможно сложные и трудные для понимания.

Причина, по которой существует util.inherits, заключается в том, что вам не нужно беспокоиться о том, как создается цепочка прототипов. Создав его самостоятельно, вы часто сталкиваетесь с проблемой, с которой вы столкнулись.

Кроме того, поскольку в настоящее время выполнения узла (> 6,0) также включает в себя большую часть спецификации ES6, вы можете (и действительно нужно) написать код, как:

const util = require('util'); 
const EventEmitter = require('events').EventEmitter; 

const Account =() => { 
    EventEmitter.call(this); 
    this.balance = 0; 
}; 
util.inherits(Account,EventEmitter); 

Account.prototype.deposit = (val) => { 
    this.balance += val; 
    this.emit('balanceChanged'); 
}; 

Account.prototype.withdraw = (val) => { 
    this.balance -= val; 
    this.emit('balanceChanged'); 
}; 

Использование ключевого слова уверяет const создаваемые вами переменные не могут быть изменены непреднамеренно или неожиданно.

И использование определения функции идиомы «жира стрелка» (() => {}) является более емким и, следовательно, быстрее набирать, но и несет в себе дополнительное преимущество, что она сохраняет значение this от окружающего контекста, так что вы никогда не должны написать что-то вроде:

Account.prototype.doSomething = function() { 
    var self = this; 

    doSomething(val, function(err,res){ 
    if(err) { 
     throw err; 
    } 
    self.result=res; 
    }); 
}; 

, который, используя «жирную стрелку» построить становится:

Account.prototype.doSomething =() => { 
    doSomething(val, (err,res) => { 
    if(err) { 
     throw err; 
    } 
    this.result=res; // where 'this' is the instance of Account 
    }); 
}; 

«жирную стрелка» идиома также позволяет сделать некоторые вещи более лаконично, как:

// return the result of a single operation 
const add = (a,b) => a + b; 

// return a single result object 
const getSum = (a,b) => {{a:a,b:b,sum:a+b}}; 

Другой способ создания наследуемые «классов» в ES6 является использование его строительства класса обозначения:

const EventEmitter = require('events'); 

class Account extends EventEmitter { 

    constructor() { 
    super(); 
    this._balance = 0; // start instance vars with an underscore 
    } 

    get balance() {  // and add a getter 
    return this._balance; 
    } 

    deposit(amount) { 
    this._balance += amount; 
    this.emit('balanceChanged'); 
    } 

    withdraw(amount) { 
    this._balance -= amount; 
    this.emit('balanceChanged'); 
    } 

} 

Следует отметить, что оба способа построения наследуемые прототипичный объектов действительно то же самое, за исключением того, что идиома нового класса добавляет синтаксический «сахар», чтобы принести декларацию в соответствие с другими языками, которые поддерживают более классическую ориентацию объекта.

Расширения ES6 к узлу предлагают много других преимуществ, заслуживающих изучения.

Смежные вопросы