Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node.JS EventEmitter Listener Must be a Function

I am getting an error when attempting to setup listeners within a function. I have reviewed other code that this works for, but can't seem to get it to work for my purposes.

This is a simplified version of what I am attempting to get done.

var ticketGenerator = function(){
    var self = this;
    console.log('ticket generator');
    var rows = "";
    this.emit("getQueue")

    var _getQueue = function(){
    console.log('Getting Queue');
    var connection = mysql.createConnection({
        //Connection Data
    }); 
    connection.connect();
    connection.query("SELECT * FROM `queue` WHERE `run` = 0 ORDER BY `queueID` ASC LIMIT 1", function(err, rows, fields){
        if(err){
            //self.emit("error", "Unable to get data from the database.")
            console.log(err);
        }
        else if(typeof rows[0] == "undefined"){
            console.log("Waiting to run again.");
            connection.end();
            setTimeout(function(){ticketGenerator()}, 60000);
        }
        else{
            console.log("Passing Ticket Data");
            self.emit("newTicketData", rows);
            connection.end();
        }
    })
    };

    this.on("getQueue", _getQueue);
}

I cannot get it to run the function for _getQueue. When I put in the listener _getQueue() it will run the function, but throws an error (TypeError: listener must be a function). I'm not sure what I am doing wrong as I have seen other code written in this way that is working.

I have verified that I have the listeners setup with this.on('newListener' . . . ). I assume that since I can get it to call the function when changing the name on the listener that the emitter is doing it's job as well.

Note that this ticketGenerator function is being called from another file using requires. I don't know if this will affect the solution for this issue, but figured that detail may be important.

---------------EDIT---------------- I ended up figuring this out after I posted this. I needed to call a constructor for these events to go through. The code looks like the following.

events.EventEmitter.call(this);

I couldn't answer my own question due to rep, but will update the answer area when I can.

like image 260
Thom Duran Avatar asked Apr 15 '13 22:04

Thom Duran


People also ask

How do I add a listener to EventEmitter?

on(event, listener) and eventEmitter. addListener(event, listener) are pretty much similar. It adds the listener at the end of the listener's array for the specified event. Multiple calls to the same event and listener will add the listener multiple times and correspondingly fire multiple times.

How are functions called when an EventEmitter object emits an event?

When the EventEmitter object emits an event, all of the functions attached to that specific event are called synchronously. Any values returned by the called listeners are ignored and discarded. The following example shows a simple EventEmitter instance with a single listener.

How do I fix a process out of memory exception in NodeJS?

This exception can be solved by increasing the default memory allocated to our program to the required memory by using the following command. Parameters: SPACE_REQD: Pass the increased memory space (in Megabytes).


1 Answers

Here's a solution to different of your problems:

  • In your sample, self will be associated with the window or global namespace. There's no way you can access your EventEmitter using this.
  • You emit the first getQueue event before attaching a listener. You must instantiate your TicketGenerator and then emit the first getQueue to get the wheel started.
  • In your timeout, just need to emit a new getQueue to retry, no need to instantiate the TicketGenerator again.

Hope this helps.

TicketGenerator = function() {
    var self = this;
    console.log('ticket generator');
    var rows = "";

    EventEmitter.call(this);

    var _getQueue = function() {
        console.log('Getting Queue');
        var connection = mysql.createConnection({
            //Connection Data
        }); 
        connection.connect();
        connection.query("SELECT * FROM `queue` WHERE `run` = 0 ORDER BY `queueID` ASC LIMIT 1", function(err, rows, fields){
            if(err){
                //self.emit("error", "Unable to get data from the database.")
                console.log(err);
            }
            else if(typeof rows[0] == "undefined"){
                console.log("Waiting to run again.");
                connection.end();
                setTimeout(function(){
                    self.emit('getQueue');
                }, 60000);
            }
            else {
                console.log("Passing Ticket Data");
                self.emit("newTicketData", rows);
                connection.end();
            }
       });
    }

    this.on("getQueue", _getQueue);
};

// Instantiate the ticket generator and initiate the first queue retrieval
var ticketGenerator = new TicketGenerator();
ticketGenerator.emit('getQueue');
like image 72
Joel Grenon Avatar answered Sep 17 '22 02:09

Joel Grenon