22

I have got a very basic example. This question has been asked previously multiple times in stack overflow itself but I could not get the right answer so I am going with this basic example.

Server:

var app    = require('express')();
var server = require('http').Server(app);
var io     = require('socket.io')(server);

server.listen(3000);

app.get('/', function (req, res) {
  res.sendfile(__dirname + '/index.html');
});

io.on('connection', function (socket) {
  socket.on('chat', function (data) {
    var op = false;
    if( data.id == '1234' ){
       op = 'yes';
    }else{
       op = 'no';
    } 
    socket.emit('result', { hello: op });
  });
});

Client:

<html>
    <body>
        <button onclick="check()">Test Me :-)</button>
        <script src="/socket.io/socket.io.js"></script>
        <script>
          var socket = io.connect('http://localhost:3000');

          var check = function(){

            var data = { id : '234'};
            socket.emit('chat', data);

            socket.on('result', function(data){
                console.log('The data is '+data)
            })
          }
        </script>
    </body>
</html>

When I click the test me button for the first time socket.emit('result', { hello: 'world' }); it is emitted one time. And in the console I am getting this printed:

console.log('The data is '+data)

But when I click once again I get this printed thrice:

console.log('The data is '+data)
console.log('The data is '+data)
console.log('The data is '+data)

When I click for the third time I get printed six times:

console.log('The data is '+data)
console.log('The data is '+data)
console.log('The data is '+data)
console.log('The data is '+data)
console.log('The data is '+data)
console.log('The data is '+data) 

Like this it is multiplying and going.

Can anyone please give me the insight on how to solve this problem. Your help is greatly appreciated. Thanks!

Finn
  • 168
  • 2
  • 3
  • 15
sdg
  • 1,306
  • 1
  • 13
  • 26

4 Answers4

24

I think you are adding more and more listeners to 'result' each call you make to check.

First time click -> call 1 console.log from call 1 listener

Second time click -> call 1 console.log from call 1 listener + call 2 console.log from call 1 listener + call 2 console.log from call 2 listener

Third time -> The previous logs + call 3 console.log from call 1 listener + call 3 console.log from call 2 listener and call 3 console.log from call 3 listener.

Try putting the listener for 'result' out of the function:

<html>
 <body>
    <button onclick="check()">Test Me :-)</button>
    <script src="/socket.io/socket.io.js"></script>
    <script>
      var socket = io.connect('http://localhost:3000');

       socket.on('result', function(data){
            console.log('The data is '+data)
        })
      var check = function(){

        var data = { id : '234'};
        socket.emit('chat', data);
      }
    </script>
 </body>
</html>
cesarluis
  • 897
  • 6
  • 14
22

For the client side you can use socket.once() instead of socket.on(). Example:

socket.once('result', function(data){
 console.log('The data is '+data)
})

Reference: https://socket.io/docs/v3/listening-to-events/#socket-once-eventName-listener

Paolo
  • 20,112
  • 21
  • 72
  • 113
Shivam Sagar
  • 247
  • 2
  • 6
2
socket.off('recive-message').on("recive-message", (data) => {
  console.log(data,'recive');
  setMessageList((list) => [...list, data]);
});
socket.off('recive-join').on("recive-join", (data) => {
  console.log(data, "join");
  setJoin(dat`enter code here`a.name);
});

In my case, this off() before on() solved my issue in React.

Tyler2P
  • 2,324
  • 26
  • 22
  • 31
1

I didn't read the question, but I'm putting this on here to help the others, cause I hadn't find this kind of answer yet.

In my case, I was calling the function next multiple times, just like so

io.use(async (socket, next) => {
    let req = socket.request
    let res = req.res || {}

    someMiddleware()(req, res, next)
    anotherMiddleware({extended: false})(req, res, next)
    anotherMiddleware()(req, res, next)
    anotherMiddleware(req, res, next)
    anotherMiddleware()(req, res, next)
    anotherMiddleware()(req, res, next)
})

Every time I was calling a middleware, the next function was getting called and on('connection') was being called too. What I got to do was overwrite the next and put it inside the last middleware, so connection get called just once.

. . .
let originalNext = next
next = () => {} // NOW its not going to annoy anymore
someMiddleware()(req, res, next)
anotherMiddleware({extended: false})(req, res, next)
anotherMiddleware()(req, res, next)
anotherMiddleware(req, res, next)
anotherMiddleware()(req, res, next)
anotherMiddleware()(req, res, originalNext) //next get called <
. . . 
Marcelo
  • 1,486
  • 13
  • 16