0

i'm newie in es6 and eventEmitter both. i've prepare a module in node event base style and now i'm trying to transform as es6 calass style. here it is

// eventStyle.js

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

var Customer = function() {
  // console.log(typeof this);
  events.EventEmitter.call(this);
  //    this is only public function
  this.register = function(email, password) {
  var newCustomer = {email:email, password:password}
  this.emit("newRegistation", newCustomer)
  }

  var _validate = function(customer) {
  if(customer.password=='password')
  this.emit("validated", customer)
  else
  this.emit("registationFailed", customer)
  }

  var _insert = function(customer) {
  this.emit("added", customer)
  }

  var _sendEmail = function(customer) {
  this.emit("emailSent", customer)
  }

  var _registationSuccessful = function(customer) {
  this.emit("registationSuccessful", customer)
  }

  this.on("newRegistation", _validate)
  this.on("validated", _insert)
  this.on("added", _sendEmail)
  this.on("emailSent", _registationSuccessful)
}

util.inherits(Customer, events.EventEmitter )

module.exports = Customer

//eventApp.js

const Customer = require('./eventStyle');
customer = new Customer();
// console.log(customer);
customer.on("registationSuccessful", ()=>{
  console.log("well done");
})

customer.on("registationFailed", ()=>{
  console.log("sorry error");
})
console.log(typeof customer.register);
setTimeout(()=>customer.register(), 1000);

//now my es6 based code (not working for me ) of eventStyle.js

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

class Customer {
  constuctor(){
  console.log("cons",this);
  events.EventEmitter.call(this);
  this.on("newRegistation", _validate)
  this.on("validated", _insert)
  this.on("added", _sendEmail)
  this.on("emailSent", _registationSuccessful)
  }

  //    this is only public function
  register(email, password) {
  var newCustomer = {email:email, password:password}
  console.log(this);
  this.emit("newRegistation", newCustomer)
  }

  _validate(customer) {
  if(customer.password=='password')
  this.emit("validated", customer)
  else
  this.emit("registationFailed", customer)
  }

  _insert(customer) {
  this.emit("added", customer)
  }

  _sendEmail(customer) {
  this.emit("emailSent", customer)
  }

  _registationSuccessful(customer) {
  this.emit("registationSuccessful", customer)
  }
}
util.inherits(Customer, events.EventEmitter )

module.exports =  Customer

somebody tell what i'm mistaking. thanks in advance

shivshankar
  • 2,067
  • 1
  • 18
  • 28

2 Answers2

2

Five Four main issues:

  1. You've missed out the first 'r' in constructor

  2. You need to use this when referring to object methods

  3. You need to preserve this in callbacks (see How to access the correct this inside a callback?). In this specific case, you don't; EventEmitter's on calls them with this set correctly (reference). If that guarantee weren't provided, you would.

  4. You need extends events on the class line (the more normal thing to do would be to call the import EventEmitter and then use extends EventEmitter).

  5. You don't use this style to call the super constructor with class events.EventEmitter.call(this);. Instead, you call super. You must do so before any use of this.

So the minimal changes version is

class Customer extends events {

and in the constructor:

constructor() { // Added missing 'r' in "constructor"
    super();    // Added
    console.log("cons", this);
    // Removed `events.EventEmitter.call(this);` here
    // On all four of the following, note `this.`
    this.on("newRegistation", this._validate);
    this.on("validated", this._insert);
    this.on("added", this._sendEmail);
    this.on("emailSent", this._registationSuccessful);
}

But, if you don't want the _ methods to be public, there's no need for them to be public; just create them in the constructor:

class Customer {
    constructor() {
        super();
        console.log("cons", this);

        const _validate = customer => {
            if (customer.password == 'password')
                this.emit("validated", customer);
            else
                this.emit("registationFailed", customer);
        };

        const _insert = customer => {
            this.emit("added", customer);
        };

        const _sendEmail = customer => {
            this.emit("emailSent", customer);
        };

        const _registationSuccessful = customer => {
            this.emit("registationSuccessful", customer);
        };

        this.on("newRegistation", _validate);
        this.on("validated", _insert);
        this.on("added", _sendEmail);
        this.on("emailSent", _registationSuccessful);
    }

    //    this is only public function
    register(email, password) {
        var newCustomer = {
            email: email,
            password: password
        }
        console.log(this);
        this.emit("newRegistation", newCustomer)
    }
}

That second form does create separate function objects for each instance, but the overhead of that is quite small. You'd need millions of instances of your class for it to matter.

You don't have to create them separately, you could do:

this.on("newRegistration", customer => {
    if (customer.password == 'password')
        this.emit("validated", customer);
    else
        this.emit("registationFailed", customer);
});

...and so on. But if you did, the function would be anonymous, which is less helpful in stack traces and such if something goes wrong. (Whereas the ones in const _validate = ... form have names.)


About calling super: If you want to pass along constructor parameters, you can do that by using rest notation:

constructor(...args) {
    super(...args);
    // ...
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
1

Almost done, missing only extends to event emitter and call to super in constructor to initialise super class (if you don't, this doesn't exist) :

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

class Customer extends events {
  constructor(){
  super();
  console.log("cons",this);
  this.on("newRegistation", this._validate)
  this.on("validated", this._insert)
  this.on("added", this._sendEmail)
  this.on("emailSent", this._registationSuccessful)
  }

  //    this is only public function
  register(email, password) {
  var newCustomer = {email:email, password:password}
  console.log(this);
  this.emit("newRegistation", newCustomer)
  }

  _validate(customer) {
  if(customer.password=='password')
  this.emit("validated", customer)
  else
  this.emit("registationFailed", customer)
  }

  _insert(customer) {
  this.emit("added", customer)
  }

  _sendEmail(customer) {
  this.emit("emailSent", customer)
  }

  _registationSuccessful(customer) {
  this.emit("registationSuccessful", customer)
  }
}

module.exports =  Customer
Fefux
  • 964
  • 5
  • 12
  • Error: SyntaxError: 'super' keyword unexpected here – shivshankar Aug 18 '17 at 14:20
  • Fixed, typo mistake : `constuctor` => `constructor` – Fefux Aug 18 '17 at 14:27
  • I don't agree, only the class which extends events is going to call emit, so this is the caller Customer and always the caller Customer. I just do the test, and `this` still my instanciated object, no need of bind – Fefux Aug 18 '17 at 14:36
  • @Fefux: (If you don't `@` notify, I don't receive notification of the comment.) In this **specific** case, you're quite right; [`EventEmitter` guarantees](https://nodejs.org/api/events.html#events_passing_arguments_and_this_to_listeners) that `this` will be set to the instance by `on`. – T.J. Crowder Aug 18 '17 at 15:40
  • thanks @Fefux . you correct TJ & me, really appreciable – shivshankar Aug 21 '17 at 11:49