Reputation: 1085
I got a RubyOnRails application that uses a Node.js/Socket.io server to push out trading information to all clients connected. Whenever a trade is executed the client screens get updated with the information of the last trade.
As the trading frequency increases, it gets rather annoying that the update happens every second or even more frequent. I am looking for a way to e.g. push the updates to the clients only max. once every 5 seconds, i.e. if no trade happens then nothing is pushed.
What I have so far is: I push the trading info to Redis from the Rails application via:
REDIS.publish('tradeupdate', ..... )
and the Node server does something like:
cli_sub.subscribe("tradeupdate");
cli_sub.on("message",function(channel,message) {
io.sockets.emit('ablv', message);
});
and the client then does
socket.on('ablv', function (data) {
obj = JSON.parse(data);
.....
});
The aim is to have only the last message within a given period (e.g. 5 seconds) to be send out from Rails to Node or from Node to clients.
Upvotes: 2
Views: 2097
Reputation: 718
What's stopping you from buffering the messages, and using a simple timer to perform the emit once every five seconds?
var last_message = null;
cli_sub.subscribe("tradeupdate");
cli_sub.on("message",function(channel,message) {
last_message = message;
});
setInterval(function() {
io.sockets.emit('ablv', last_message);
}, 5000);
Upvotes: 2
Reputation: 3160
It looks like what you need here is a helper for throttling your function calls. For example:
var makeThrottler = function() {
var toRun = null, timeout = null;
function doRun() {
if (!toRun) {
// nothing to run; we set timeout to null so that the
// next function to execute knows to run immediately
timeout = null;
return;
}
// set a timeout of 5s before
timeout = setTimeout(function() {
doRun();
}, 5000);
// we need to do this temp thing to protect against
// calling executeThrottled again within toRun
var temp = toRun;
toRun = null;
temp();
}
function executeThrottled(fn) {
// this is the function we want to execute next; it
// overwrites any function we've stored earlier
toRun = fn;
// if we already ran within the last 5 seconds, don't do
// anything now (our function will be called later)
if (timeout)
return;
// execute the function right away
doRun();
}
return executeThrottled;
}
And here's an example of how to use it:
var throttled = makeThrottler(), x = 0;
function increment() {
throttled(function() {
console.log(x);
});
x++;
setTimeout(increment, 1000);
}
increment();
The increment function increases x
by one every second. The logging is throttled, so the output you will see is 0, 5, 10, etc. (They might be occasionally off by one because of slight timing inaccuracies.)
Your original code would become something like:
cli_sub.subscribe("tradeupdate");
cli_sub.on("message",function(channel,message) {
throttled(function() {
io.sockets.emit('ablv', message);
});
});
Upvotes: 1