How to handle any event itself in socket.io - node.js

I need to run some function for every event from client in server node.js/socket.io
This is about calculate average time between events so I can detect spamers.
Any ideas? In docs I didn't find it. Something like:
socket.onAnyEvent( function() {
//do things
});

Here is a good thread: https://github.com/LearnBoost/socket.io/issues/434 specifically you can extend the emitter.

Related

How to iterate on each record of a Model.stream waterline query?

I need to do something like:
Lineup.stream({foo:"bar"}).exec(function(err,lineup){
// Do something with each record
});
Lineup is a collection with over 18000 records so I think using find is not a good option. What's the correct way to do this? From docs I can't figure out how to.
The .stream() method returns a node stream interface ( a read stream ) that emits events as data is read. Your options here are either to .pipe() to something else that can take "stream" input, such as the response object of the server, or to attach an event listener to the events emitted from the stream. i.e:
Piped to response
Lineup.stream({foo:"bar"}).pipe(res);
Setup event listeners
var stream = Lineup.stream({foo:"bar"});
stream.on("data",function(data) {
stream.pause(); // stop emitting events for a moment
/*
* Do things
*/
stream.resume(); // resume events
});
stream.on("err",function(err) {
// handle any errors that will throw in reading here
});
The .pause() and .resume() are quite inportant as otherwise things within the processing just keep responding to emitted events before that code is complete. While fine for small cases, this is not desirable for larger "streams" that the interface is meant to be used for.
Additionally, if you are calling any "asynchronous" actions inside the event handler like this, then you need to take care to .resume() within the callback or promise resolution , thus waiting for that "async" action to complete itself.
But look at the "node documentation" linked earlier for more in depth information on "stream".
P.S I believe the following syntax should also be supported if it suits your sensibilities better:
var stream = Lineup.find({foo:"bar"}).stream();

How to customize socket.io's connection event by room?

When a socket connects to a socket.io server, a connection event is triggered. The function that handles such event can be overrided to add custom behavior to the connection.
I want to add a function to handle the connection event, but for a socket.io room.
I was trying something like (with socket.io 0.9.14):
io.sockets.in('someNamespace/someRoom').on('connection', function () {
//custom actions here
}
But it doesn't seem to work. The behavior is attached to the default connection event and triggered on every connection.
Is it possible to achieve what I'm trying? any suggestions?
Thanks in advance.
If I've understood your question clearly, you're trying to use namespaces. Then you should do it like this:
io.of('/someNamespace/someRoom').on('connection', function (socket) {
//your actions here
});
It is possible to simulate a similar behavior (similar to the on-connection handler) for rooms, using the callback (or fn) argument for the socket.io 0.9.14 join function, like this:
socket.join('some/room', function handleJoin () {
//do something when socket joins to 'some/room'
})
For the version 0.9.14 of socket.io, when the join function has a second argument, a warning is displayed telling:
Client#join callback is deprecated
But for the current one, in the master branch (version 1.0.0-pre), the warning is no longer there and the callback function can be used for error handling on room joining. So, it might be safe to rely on the existence of this argument in the future.
Finally, by using a wrapper function on the join call, it is possible to preserve the closure for the call, thus providing the same arguments that an on connection handler normally takes.
e.g. (in some place inside the server)
var someVar = 'some value';
socket.join('some/room', function () {
handleJoin(someVar);
});
And then, somevar will be available inside the handleJoin function (somevar could be the room name, for example). Of course, it is a very simple example and it could be adapted to meet different requirements or to comply with the upcoming version of the join function.
Hope this helps.

Why "close" event when something goes wrong with node-amqp?

(I am using node-amqp and rabbitmq server.)
I am trying to guess why I have a close event if something goes wrong. For example, If I try to open a a connection to a queue (with bad parameters) I receive an error event. That it is perfect ok.
But, after any error I will receive also a close connection (in that case, maybe because close the failed socket to the queue). And after that, auto-reconnect and I receive the (initial) ready event.
The problem:
connection.on('ready', function() {
do_a_lot_of_things
}).on(error, function(error){
solve_the_problem
});
if something goes wrong, I receive the error, but then "ready" event and it will re do_a_lot_of_things. Is my approach wrong?
best regards
You can use connection.once('ready', function () { … }) (see the documentation), which will execute the handler only on the first event.

node.js - ensuring one event occurs before another

I'm new to node.js and learning...
I have the following 2 socket.io listeners and I need to ensure the .on happens before the .once (currently the .once occurs first):
io.on('connection', function (socket) {
io.once('connection', function (socket) {
is there a good way to ensure the .once occurs fist always?
This may not work because you are creating two independent functions. Usually, for event listeners, that is good. In this case, you need them coupled.
What you can do is subscribe using on and have the handler figure out if it has run before or not.
io.on('connection', function (socket) {
if (!this.called) {
// do what you want to do only the first time
this.called = true;
}
// do whatever you want to do every time
}.bind({ called: false });
This creates a wrapper function which keeps track of whether or not it has been called and does something special when it is called for the first time.
So when you have these order dependencies, it's best to code for them explicitly. Events are great when operations are truly independent, but when operations have interdependencies, better to make that obvious in code. In general, don't assume anything about the order in which event sources will invoke the bound event handler functions. Therefore, try something like this pseudocode:
io.on('connection', firstConnection);
function firstConnection(socket) {
//do first connectiony stuff here
io.on('connection', allConnections);
io.off('connection', firstConnection);
allConnections(socket);
}
function allConnections(socket){ /*all connectiony stuff here */}

Pushing changes to all clients with Node.js and Socket.io

I have a working server that's using sockets. My server-side code looks like this:
io.sockets.on('connection', function(socket) {
socket.emit('status', { counter: count });
});
In this example, I'm simply incrementing a counter by 1 every minute. When the counter updates, I'd like to send the current count to all clients. My index.html file looks like this:
<script>
var socket = io.connect('http://localhost');
socket.on('status', function (data) {
console.log(data);
});
</script>
When I start up my server, I can see the first data send to the client {'counter': 0}, however when the value of the counter increments, I don't see the new value being updated on the client. Why isn't new data being sent to my clients?
You emit the information only upon connection. For instance, if you just want to broadcast the information every minute - just change your code to:
io.sockets.on('connection', function(socket) {
setInterval(function() {
socket.emit('status', { counter: count });
}, 60 * 1000);
});
This will create an interval upon connection, and then emit the message every minute.
If you want something more advanced, such as listening to the change in count you need to subscribe to changes from it using a more advanced mechanism.
Update
Another way to achieve this is to emit on counter change (using the same function that updates it).
Yet another way is to use the experimental observe feature on a javascript object.
This question was already answered.
See: Update all clients using Socket.io?
The basic info is: you need to emit the message form the global socket io not the individual socket.
The socket.emit() only emits to one socket. Where as io.socket.emit() will emit the message to all sockets (broadcast message).

Resources