Ad

Emitting Multiple Times

- 1 answer

I've read through the site and googled, and can't seem to find an answer that will work for me.

I've set up a super super basic example of using Socket.IO until I can get my head around, all it does is passes a number to the back end, adds +1 and send it back to front end.

It does work however, each interval round, it emits more and more (which I can see using console.log on the server side.) I'm only connected using one computer to test.

Can someone help me please. I understand its probably because the emit is inside the connection but I just can't quite click in my head on how to overcome this.

I've tried moving bits around, moving the function out of the connection. I've tried multiple ideas from google, but nothing seems to solve it.

const io = require('socket.io')();

io.on('connection', (socket) => {
  socket.on('subscribeToAddition', (additon,interval) => {
    console.log('current number... ', additon);
    setInterval(() => {
      socket.emit('addition', additon+1);
    }, interval);
  });
});

const port = 8000;
io.listen(port);
console.log('listening on port ', port);

the interval variable is set as 5 seconds in my react component. I just want it to log/update once every five seconds instead of log once, then twice, then 4 times, then 8 times, etc

Ad

Answer

Given the symptoms, it's likely that you're sending the subscribeToAddition event more than once on the same socket and thus starting more than one timer for the same socket and thus you get duplicate messages.


Proper indentation of your code makes things a little clearer:

const io = require('socket.io')();

io.on('connection', (socket) => {

    socket.on('subscribeToAddition', (additon, interval) => {

        console.log('current number... ', additon);

        setInterval(() => {
            socket.emit('addition', additon + 1);
        }, interval);

    });

});

const port = 8000;
io.listen(port);
console.log('listening on port ', port);

I want to make sure you understand that setInterval() starts a repeating timer that goes forever until you call clearInterval() on the timerId that it returns.

Problems I see:

  1. In every subscribeToAddition message, you're adding a new setInterval() timer. So, if you send the subscribeToAddition twice, you will have two setInterval() timers each going on the same socket.

  2. Those setInterval() timers will accumulate and never go away because you have no way of the client stopping them and they don't go away even when the socket closes. They will just cause errors because socket.emit() won't work on a closed socket, but they will probably even prevent garbage collection of the old socket.


It is not clear exactly how you want this to work, but here's a cleaned up version:

const io = require('socket.io')();

io.on('connection', (socket) => {

    function clearTimer() {
        if (socket.myTimer) {
            clearInterval(socket.myTimer);
            delete socket.myTimer;
        }
    }

    socket.on('subscribeToAddition', (additon, interval) => {

        console.log('current number... ', additon);

        // don't start a new interval timer if one is already running
        if (!socket.mytimer) {

            socket.mytimer = setInterval(() => {
                socket.emit('addition', ++additon);
            }, interval);
        }

    });

    socket.on('unSubscribeToAddition', () => {
        clearTimer();
    });

    socket.on('disconnect', () => {
        clearTimer();
    });

});

const port = 8000;
io.listen(port);
console.log('listening on port ', port);

This version makes the following modifications:

  1. Keeps track of the timerID from setInterval() so we can stop it in the future. For convenience, we store it as a custom property on the socket object so that each connected socket has its own timer.
  2. Adds an unsubscribeToAddition message so the client can stop the timer.
  3. Adds a disconnect message handler so you can stop the timer when the socket disconnects.
  4. Increments the additon variable on each tick of the timer.
Ad
source: stackoverflow.com
Ad