Correct use of socket.io events's callbacks

I was reading this interesting introductory article about how socket.io's events and callbacks work.

I decided to give first try with something as follows.

First try

server.js

// client is the socket for the client
client.on('foo' , function(callback){
  callback("Hello world");
});

client.js

// server is the socket for the server
server.emit('foo', function(msg){
  alert(msg);
});

Well, it just so happens that it actually didn't work (the server throws an exception telling callback is not a function). Trying to solve that, I found this answer explaining how to do it the right way. Well, that didn't work either. A few modifications and I got to this...

Second try

server.js

// client is the socket for the client
client.on('foo' , function(name, callback){
  callback("Hello world");
});

client.js

// server is the socket for the server
server.emit('foo',{},function(msg){
  alert(msg);
});

Well, it works perfectly, but having to add that "name" parameter and that empty hash which I don't use seems to be a a not-so-good solution.

I tried to find the explanation of this in the amazingly incomplete socket.io's documentation, but found no explanation for this beheaviour, which is why I'm asking here.

Another doubt that I have is if it possible to do the same to the other side (i.e., the server sending a callback to the client, and then the callback getting executed in the server), but I haven't tried yet.

TL;DR: Why the first try doesn't work and the second one does? Is there a way to avoid that useless empty hash and name argument?. Does this work the same the both ways? (server→client and client→server).

The empty object doesn't have to be an object, it can be virtually anything, such as a string, or maybe even null (haven't tried that). Also the name parameter isn't specifically a "name" parameter, it's simply whatever data you passed from the client (again, that could be the empty object you are currently using, or anything else). A better generic parameter name might be data. Sure, you could call it a waste, but it's only two characters that you're transferring, and most of the time you'll probably find a use for that data.

The third argument you're passing to emit (a function) is the optional callback parameter, and obviously since it's working, you're using it right.

As to going in the reverse direction, I've never tried that either. It's likely to work, but even if it doesn't, all you have to do is send a unique ID along with each of your push events, and then have the client emit an event back to the server with that ID, and write some code on the server which reassociates that event with the original push event. You could even use a counter on each socket as your push ID, and then use the combination of socket.id and event.id as a unique identifier.