miguelfsf
miguelfsf

Reputation: 97

Node js event listener not working as expected

So im basically trying to emit and listen to a specific event on different typescript classes. The first event that is emitted is being listened properly on the other class but once I set a timeout to emit other event after 10 seconds for example, its like the listener is not listening anymore..

commonEmitter.ts

let events = require('events');
let em = new events.EventEmitter();
module.exports.commonEmitter = em;

network.ts

export class Network {

  constructor() {
    this.setConnection('connected');

    setTimeout(() => {
      commonEmitter.emit('connectionStatusChanged');
      connection = 'disconnected';
    }, 10000);
  }

private setConnection(newConnection): void {
      connection = newConnection
      commonEmitter.emit('connectionStatusChanged');
}

public isConnected(): boolean {
    return connection === 'connected';
}

}

export let connection = null;

view.ts

export class View {

private network: any;

constructor() { }


private test(){
   console.log('Online? ' + this.network.isConnected());
}

public init(){

commonEmitter.on('connectionStatusChanged', this.test());

this.network = new Network();

}

At the end, both of the events are emitted but only the first one is being "listened". Whats the reason for that and how I can do it in an ordered way?

Upvotes: 1

Views: 2423

Answers (4)

miguelfsf
miguelfsf

Reputation: 97

By using this solution, now the first event that is emitted from the network class is never listened.. only after the timeout it works and refreshes the view but I don't know why the first one does not:/

// network.ts

commonEmitter.emit('connectionStatusChanged', {isOnline: true});

// view.ts

commonEmitter.on('connectionStatusChanged', (data: any) => {
      console.log('Online? ' + data.isOnline);
});

Upvotes: 0

kicito
kicito

Reputation: 99

To answer the second question, you should've pass an object as a argument to emit

// network.ts
commonEmitter.emit('connectionStatusChanged', {data: true});

Upvotes: 1

miguelfsf
miguelfsf

Reputation: 97

The arrow function combined with the test function call worked for me so thanks alot @jfriend000 :p The one with the bind method didn't work but it's ok.

I just have one more question, every time I try to emit and event with any type of arguments the listener is not listening to that. For example:

// view.ts
commonEmitter.on('connectionStatusChanged', (data: boolean) => {
   console.log(data);
}); 

// network.ts
commonEmitter.emit('connectionStatusChanged', true);

If this is also related to the context, how should it be done?

Upvotes: 0

jfriend00
jfriend00

Reputation: 707158

In this line of code:

commonEmitter.on('connectionStatusChanged', this.test()); 

You're calling this.test() immediately, not passing a function reference that can be called LATER. Change it to this:

commonEmitter.on('connectionStatusChanged', this.test.bind(this)); 

So, you're properly passing a function reference that will also be properly bound to this.


Or, you could use a fat arrow callback function that will preserve the lexical value of this like this:

commonEmitter.on('connectionStatusChanged', () => {
    this.test();
}); 

Upvotes: 1

Related Questions