Rich
Rich

Reputation: 4248

How to use removeListener in node.js/socket.io to prevent multiple triggered function

I'm having a problem about socket.io/node.js. I'm emitting client to server and vice versa and it triggering my function more than one even though I'm just triggering it once. So here's my code

Client side;

for (var x = circles.length - 1; x >= 0; x--) {
    if (circle.eat(circles[x])) {
        position = {
             x: circles[x].position.x,
             y: circles[x].position.y,
             r: circles[x].position.r,
             index: x
        };
        circles.splice(x, 1);
        socket.emit('eat', position); //Here's the emit to server.
   }
}

Server Side;

var events = require('events');
var eventEmitter = new events.EventEmitter();

socket.on('eat',
    function(data){
    circlePosition.splice(data.index, 1);
    counter++;
    eventEmitter.removeListener('eat', this); //Removing this listener but planning to use it again by adding it again using addListener
});

I already tried to compare the incoming datas to the recently sent datas by an if else to avoid duplication of datas even it will be triggered multiple times but still the problem occur, and if I use that method the precision of data will be a problem. So I'm trying to use a removeListener and addListener but the the error is;

enter image description here

How to get rid of this?

EDIT

I've tried to make the listen variable make true again once it is emitted from client to server, here's the code

Client Side:

for (var x = circles.length - 1; x >= 0; x--) {
    if (circle.eat(circles[x])) {
        position = {
            x: circles[x].position.x,
            y: circles[x].position.y,
            r: circles[x].position.r,
            index: x,
                        listen: false   //Condition to if else in server side
        };
        circles.splice(x, 1);
        socket.emit('eat', position); //Here's the emit to server.
    }
}

Server Side:

socket.on('eat', eatFunction);

function eatFunction(data){
    if(!data.listen){   //listen variable used inside the if else block
        circlePosition.splice(data.index, 1);
        counter++;
        data.listen = null;
        console.log(data.listen + " " + counter); //to see if the listen becomes null and the counter to see how many times it triggers
        eventEmitter.removeAllListeners('eat', eatFunction);
    }
}

I think the problem is the Client side because it sends more than it should, not the receiving.

Upvotes: 1

Views: 4015

Answers (1)

Kevin Workman
Kevin Workman

Reputation: 42176

Look at this line:

eventEmitter.removeListener('eat', this);

What object do you think this refers to here? It seems like you think it's referring to the function, but that's not the case. The this keyword in JavaScript can be a little tricky, but basically it's going to refer to the instance that contains the function, not the function itself.

You need to pass a reference to the function itself. It might be easier if you stop using an inline function and use a named function instead:

socket.on('eat', eatFunction);

function eatFunction(data){
    circlePosition.splice(data.index, 1);
    counter++;
    eventEmitter.removeListener('eat', eatFunction);
}

Notice that the eatFunction() now has a name, so you can use it as a parameter for both the on() and removeListener() functions.

Shameless self-promotion: I've written a tutorial on creating JavaScript functions available here.

Edit: If all you're trying to do is top reacting to events, why don't you just use a variable that keeps track of whether you should react to events? Something like this:

var listen = true;

socket.on('eat', eatFunction);

function eatFunction(data){
    if(listen){
       circlePosition.splice(data.index, 1);
       counter++;
       listen = false;
    }
}

Upvotes: 2

Related Questions