Emitting multiple times - node.js

I've read through the site and googled, and can't seem to find an answer that will work for me.
I've set up a super super basic example of using Socket.IO until I can get my head around, all it does is passes a number to the back end, adds +1 and send it back to front end.
It does work however, each interval round, it emits more and more (which I can see using console.log on the server side.) I'm only connected using one computer to test.
Can someone help me please. I understand its probably because the emit is inside the connection but I just can't quite click in my head on how to overcome this.
I've tried moving bits around, moving the function out of the connection. I've tried multiple ideas from google, but nothing seems to solve it.
const io = require('socket.io')();
io.on('connection', (socket) => {
socket.on('subscribeToAddition', (additon,interval) => {
console.log('current number... ', additon);
setInterval(() => {
socket.emit('addition', additon+1);
}, interval);
});
});
const port = 8000;
io.listen(port);
console.log('listening on port ', port);
the interval variable is set as 5 seconds in my react component. I just want it to log/update once every five seconds instead of log once, then twice, then 4 times, then 8 times, etc

Given the symptoms, it's likely that you're sending the subscribeToAddition event more than once on the same socket and thus starting more than one timer for the same socket and thus you get duplicate messages.
Proper indentation of your code makes things a little clearer:
const io = require('socket.io')();
io.on('connection', (socket) => {
socket.on('subscribeToAddition', (additon, interval) => {
console.log('current number... ', additon);
setInterval(() => {
socket.emit('addition', additon + 1);
}, interval);
});
});
const port = 8000;
io.listen(port);
console.log('listening on port ', port);
I want to make sure you understand that setInterval() starts a repeating timer that goes forever until you call clearInterval() on the timerId that it returns.
Problems I see:
In every subscribeToAddition message, you're adding a new setInterval() timer. So, if you send the subscribeToAddition twice, you will have two setInterval() timers each going on the same socket.
Those setInterval() timers will accumulate and never go away because you have no way of the client stopping them and they don't go away even when the socket closes. They will just cause errors because socket.emit() won't work on a closed socket, but they will probably even prevent garbage collection of the old socket.
It is not clear exactly how you want this to work, but here's a cleaned up version:
const io = require('socket.io')();
io.on('connection', (socket) => {
function clearTimer() {
if (socket.myTimer) {
clearInterval(socket.myTimer);
delete socket.myTimer;
}
}
socket.on('subscribeToAddition', (additon, interval) => {
console.log('current number... ', additon);
// don't start a new interval timer if one is already running
if (!socket.mytimer) {
socket.mytimer = setInterval(() => {
socket.emit('addition', ++additon);
}, interval);
}
});
socket.on('unSubscribeToAddition', () => {
clearTimer();
});
socket.on('disconnect', () => {
clearTimer();
});
});
const port = 8000;
io.listen(port);
console.log('listening on port ', port);
This version makes the following modifications:
Keeps track of the timerID from setInterval() so we can stop it in the future. For convenience, we store it as a custom property on the socket object so that each connected socket has its own timer.
Adds an unsubscribeToAddition message so the client can stop the timer.
Adds a disconnect message handler so you can stop the timer when the socket disconnects.
Increments the additon variable on each tick of the timer.

Related

Node.js and socket.io initialization setInterval()

I have an event on server that is triggered when the client sends a message:
socket.on('message', function(data){
message.push(data);
});
And now when all clients send a message, I want to wait for 3 seconds and then call a function.
I tried with Interval:
var index=0;
var timer;
socket.on('message', function(data){
message.push(data);
if (index==0) //only once
timer = setInterval(call(), 3000);
index++;
});
function call(){
io.sockets.emit("confirmation", {status: "All messages are delivered"});
clearInterval(timer); // Clear interval
}
The problem is that the function call() call immediately and not after 3 seconds.
The second problem is that clearInterval(timer) in function call, does not work because the function call repeats.
If you only want this to occur once, you should use setTimeout instead of setInterval.
This will save you from needing to clear the interval later, and makes the code more explicit that you want it to happen exactly once, 3 seconds from "now."
In addition "(...)" at the end of a function name causes it to be called immediately. You want to pass the function "call" as a parameter, not cause it to be called immediately.
I would also recommend you name the function something other than call, as this is already a name of a standard function in Javascript, and therefore can get confusing quickly. Even calling it callback would reduce confusion.
So, what you're looking for is something like this:
setTimeout(callback,3000);
in place of this
setInterval(call(), 3000);
You are making a call to the function from setInterval function.
It should betimer = setInterval(call, 3000); and not timer = setInterval(call(), 3000);
Thanks for all the answers. I solve the problem.
The problem was that I wanted to create a setInterval() within io.on("connection", function(socket){}, but it makes for each client separately. I did not want this.
Now I put before and it works:
var index=0;
var timer;
var check=false;
timer = setInterval(function(){fcall()}, 3000);
function fcall(){
if(check)
{
io.sockets.emit("confirmation", {status: "All messages are delivered"});
clearInterval(timer); // Clear interval
timer=0;
}
}
io.on("connection", function(socket){
socket.on('message', function(data){
message.push(data);
if (index==0) //only once
check = true;
index++;
});
}

NodeJS 0.10. No 'data' event emitted on net.Socket

I have code to log every connection to my HTTP-server on a socket level and also log any incoming data.
This code was originally written for NodeJS 0.8 and works good there.
No my project is migrated to 0.10.24 and socket logging code stopped working.
Here is my code:
var netLogStream = fs.createWriteStream('net.log');
(function(f) {
net.Server.prototype.listen = function(port) {
var rv = f.apply(this, arguments); // (1)
rv.on('connection', function(socket) { // (2)
socket.on('data', function(data) {
data.toString().split('\n').forEach(function(line) { // (3)
netLogStream.write('... some logging here ... ' + line);
});
});
});
return rv;
};
})(net.Server.prototype.listen);
On 0.10 I can get to (1) and get Socket instance on (2) but I never get to (3). Same time my whole application works fine without any issues.
ADD: My server is created with Express#3.4.x
I'm not sure why the results are different between node v0.8 and v0.10, but if I had to guess, I'd be looking at the return value of net.Server.prototype.listen.
According to the documentation, this is an asynchronous method which emits the 'listen' event and invokes its callback when the listening is bound. You're not looking for that event, but rather, capturing the return value of listen, which for an async function, may not be well-defined. It's obviously not null or undefined since you don't get a runtime error, but the return value may not be the same between v0.8 and v0.10.
I honestly don't know for sure because I don't do low-level socket coding, but I have 2 suggestions to try:
Since the connection event is emitted from the Server object, perhaps you need this.on instead of rv.on.
Setup the connection event listener before you invoke listen just to minimize risk of race conditions.
Try this and see what happens:
var netLogStream = fs.createWriteStream('net.log');
(function(f) {
net.Server.prototype.listen = function(port) {
this.on('connection', function(socket) { // (2)
socket.on('data', function(data) {
data.toString().split('\n').forEach(function(line) { // (3)
netLogStream.write('... some logging here ... ' + line);
});
});
});
return f.apply(this, arguments); // (1)
};
})(net.Server.prototype.listen);

nodejs - How to test whether remote socket is open

I am creating a socket pass through inspector.
Basically, I start up a socket server (net.createServer) and a socket client (net.connect). For testing purposes, I do not have a endpoint socket waiting.
I want test whether the endpoint socket is available. If not, nodejs should wait until socket is available.
var net = require('net');
var inbound = net.createServer();
var outbound = net.connect({
port: 8193
});
inbound.listen(8192, function () { //'listening' listener
address = inbound.address();
console.log('Server started on %j', address);
});
inbound.on('connection', function (insock, outbound) {
console.log('CONNECTED ' + insock.remoteAddress + ':' + insock.remotePort);
insock.on('data', function (data, outbound) {
outbound.write(data);
console.log('DATA ' + data);
});
});
The best way to test whether any resource is available is to try to use it. Pre-testing is liable to a number of objections:
If it tests something different from the actual usage, it may yield an incorrect answer.
If it tests the same things as the actual usage it is merely wastefully redundant.
The situation may change between the test and the usage.

In Socket.IO, is 'heartbeat' an event that can be used to trigger other actions?

This exact code doesn't work, but, I was hoping something like it was:
io.sockets.on('connection', function(socket) {
socket.on('heartbeat', function() {
// Do something here...
});
});
Is something like this possible? I mean, I know I can just make a different function that triggers every, say, 15 seconds using a setInterval:
io.sockets.on('connection', function(socket) {
setInterval(function() {
// Do something
},15000);
});
But since the heartbeat is already running at this interval, why not make use of it?
In any case, any insight would be greatly appreciated.
I think that I see what you're trying to do. There are a few exposed events that you can check here - list of Socket.io events - but there is no "heartbeat" event that you can tap into to fire at a set interval.
You're on the right track with the second piece of code -
setInterval(function() {
socket.emit('heartbeat', someData);
}, 5000);
And on the client side -
socket.on('heartbeat', function(data) {
console.log(data);
})

How can I detect, when the connection of the client gets interrupted in socket.io?

I have a Node.js-Server with a socket.io-connection to a browser-client. sometimes the connection gets interrupted, for example, when I need to restart the server. When that happens, how can the client know this?
Here's an example on how you can achieve that on the client side:
var chat = io.connect('http://localhost:4000/chat');
chat.on('connect', function () {
console.log('Connected to the chat!');
});
chat.on('disconnect', function () {
console.log('Disconnected from the chat!');
});
As you can see, you keep the connection variable and you use connection_variable.on('disconnect', callback_function_here)

Resources