Thom Duran
Thom Duran

Reputation: 129

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.

Upvotes: 6

Views: 5101

Answers (1)

Joel Grenon
Joel Grenon

Reputation: 3273

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');

Upvotes: 1

Related Questions