Node.js - Socket.io io.emit() doing nothing

11k views Asked by At

I'm having a problem with my socket.io applicaiton, the io.emit(), and io.sockets.emit() straight up do not work, they do nothing, and return no error.

I've provided here the most simplified version of the code I can make here.

Server:

var server = require('http').createServer();
var io = require('socket.io')(server);
var port = 8080;

io.use(function(socket, next){
  next();
});

io.of('/projects/test_cases').on('connection', function(socket){
  io.sockets.emit("test_case_changed", "test1"); // Doesn't do anything
  io.emit("test_case_changed", "test2"); // Doesn't do anything
  socket.emit("test_case_changed", "test3"); // Works
  io.to(socket.id).emit("test_case_changed", "test4"); // doesn't work

});

io.on('connection', function(socket){
  socket.on('disconnect', function(){

  });
});

server.listen(port, function(){
  console.log('listening on *:' + port);
  setTimeout(function(){
    io.sockets.emit("test_case_changed", "test"); // does nothing
    io.emit("test_case_changed", "test"); // does nothing
  }, 3000);
});

Client:

<script>
    var socket = io('http://localhost:8080/projects/test_cases');
    socket.on('error', function (reason){
      console.error('Unable to connect Socket.IO', reason);
    });
    socket.on('connect', function (){
      console.info('Connected');
    });
    socket.on("test_case_changed", function (data){
      console.log(data);
    });
</script>

As you can see, on the client side test1, test2, test3, and test4 should all print on the client, but only test3 does.

In addition, if you add the following to the on('connection') method

  console.log("Pre join: ", socket.rooms); 
  socket.join("room1"); // Doesn't work
  console.log("After join: ", socket.rooms); 

That does not work either. IE you can't make the socket join a room in that method.

2

There are 2 answers

3
Vitali Kotik On BEST ANSWER

Sockets belong to a certain namespace.

By writing io.of('/projects/test_cases').on('connection', function(socket){}); you put all connected sockets to '/projects/test_cases' namespace.

By writing

 io.sockets.emit("test_case_changed", "test1");
 io.emit("test_case_changed", "test2");

you emit to a default namespace '/' that is different from '/projects/test_cases'

You can easily see the namespace used:

console.log(io.sockets.name) // '/'
console.log(io.of('/projects/test_cases').name) // '/projects/test_cases'

You may want to explicitly specify namespace of sockets to emit messages to

io.of('/projects/test_cases').emit("test_case_changed", "test1");

UPD: As for the second part of the question you may want to know that join is an asynchronous operation. That's why room1 is not in socket.rooms right the next line of code. You may get notified when the socket is in the room using the following lines:

socket.join("room1", function(err){
    console.log("After join: ", socket.rooms);
});
0
ecarrizo On

This worked for me. It is sending a message called 'Event' to all the connected sockets once another socket is connected.

I've just removed the unused code, so try doing that first and start from scratch.

Also, the documentation work for me is not that bad.. http://socket.io/docs/ and for namespaces specific http://socket.io/docs/rooms-and-namespaces/

APP.JS

var server = require('http').createServer();
var io = require('socket.io')(server);
var port = 8080;

var nsp = io.of('/projects/test_cases');
nsp.on('connection', function(socket) {
    console.log('someone Connected!');
    nsp.emit('event', 'data');
});

server.listen(port, function(){});

index.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<script src="https://cdn.socket.io/socket.io-1.3.5.js"></script>
<script>
    var socket = io('http://localhost:8080/projects/test_cases');
    socket.on('error', function (reason){
        console.error('Unable to connect Socket.IO', reason);
    });
    socket.on('connect', function (){
        console.info('Connected');
    });
    socket.on("event", function (data){
        console.log(data);
    });
</script>
</body>
</html>

To test it open in 3 or 4 tabs the index.html file and just press refresh 5 or 6 times on one of it, then check the console for the other tabs.. it should be logged 'data' a couple of times.