Node.js and socket.io initialization setInterval() - node.js

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++;
});
}

Related

node.js - in socket callback run my function only once in a minute

Let me explain what I am trying to do:
const ws = new WebSocket(url);
ws.on('message', function (data) {
//some code
savetoToDB(result) //this is my function, that i want to be called once in a minute
});
So I making socket connection, and receive data like twice in a second. But i want to execute saveToDB function only once in a minute. How can i achieve that? Thanks!
You would need to use something called debouncing function where a function would not be executed more than once in a given time frame.
Here is a link to an implementation in JS.
Here is a link to the lodash debounce.
Using a simple variable to store the last SaveToDB time would help.
const ws = new WebSocket(url);
var savedAt = 0; //Initialization
ws.on('message', function (data) {
//some code
var currentTime = Date.now();
if(currentTime-savedAt>60000){//60000milliseconds
savetoToDB(result); //this is my function, that i want to be called once in a minute
savedAt = currentTime;
}
});

Set and clear interval in node js

I am learning node js and need some clarification.
var EventEmitter = require('events').EventEmitter;
var getResource = function(c) {
var emitter = new EventEmitter();
process.nextTick(function() {
var count = 0;
emitter.emit("start")
var t = setInterval(function() {
c
emitter.emit("data", ++count);
if (count === c) {
emitter.emit("end");
//clearInterval(t);
}
}, 1000)
});
return emitter;
}
var r = getResource(5);
r.on("start", function() {
console.log("I have started");
})
r.on("data", function(d) {
console.log("Received " + d);
})
r.on("end", function() {
console.log("I have ended");
})
If I uncomment the setInterval part it behaves as expected ie., prints the data until 5 and end event is emitted.
If I comment it, then data is printed until 5 and end event is emitted. After that it runs in indefinite loop and prints continuously. Why is my code
if(count === c){...}
does not check and ends the loop ?
The emit method is a generic one. It just emits an event & optionally passes data.
emitter.emit(eventName, data);
where eventName is a string & data is an arbitrary value.
It is up to the programmer to make use of that as per the requirement.
Passing end as event name means nothing to emit method, as for the method, it is just another call. In your case, clearInterval is needed to actually end data events. Only to the receiver of the events, end event makes sense.
So, if you emit end event, the receiver will know there would be no more data event.
Consider emitting end event as a signal to receiver. But, you have to actually make sure there are no more events(data) after end event.
until clearInterval is called, setInterval will execute the code
in recurring time intervals.
Please refer the NodeJs doc on Timers.

How do I get data from setTimeout function in NodeJS

Sometimes in nodejs I have to make a request to other host. My function have to wait until the response of this request is completed but usually they comes to next line without any waiting for the finish.
To simplify problem, I make a simple snipp code and I want to know how to get data out from this function
function testCallback(){
var _appData;
setTimeout(function(){
var a = 100;
getData(a);
}, 200);
function getData(data){
_appData = data;
}
return _appData;
}
console.log('testCallback: ', testCallback());
console.log send out undefined, I want to know with this function how to get result is 100
Basically setTimeout is asynchronous, so the code keeps going, your code it becomes, virtually like this:
function testCallback(){
var _appData;
return _appData;
}
Which, yes, it is undefined, because you do not set anything.
What you have to do is use a callback in your function, so when the long task (setTimeout) is finished you return the data.
Something like this:
function testCallback(cb){
setTimeout(function(){
var a = 100;
getData(a);
}, 200);
function getData(data){
cb(null, data);
}
}
and when calling it you have to pass a function as an argument (callback standard has 2 parameters, (err, value).)
testCallback(function(err, value) { console.log(value); });

Execute when both(!) events fire .on('end')

I have a node app that reads two files as streams. I use event.on('end') to then work with the results. The problem is I don't really know how I can wait for BOTH events to trigger 'end'.
What I have now is:
reader1.on('end', function(){
reader2.on('end',function(){
doSomething();
});
});
With small files this works, but if one of the files is very large the app aborts.
Your execution logic is somewhat flawed. You ought to do something like this instead
var checklist = [];
// checklist will contain sort of a counter
function reader_end(){
if(checklist.length == 2 )
// doSomething only if both have been added to the checklist
doSomething();
}
reader1.on('end', function() {
checklist.push('reader1');
// increment the counter
reader_end();
});
reader2.on('end', function() {
checklist.push('reader2');
reader_end();
});
Although there are libraries to better handle this sort of stuff, like Async and Promises.
With Async you'll need to use compose
var r12_done = async.compose(reader1.on, reader2.on);
r12_done('end', function(){
doSomething();
});
Edit: I just noticed that since probably reader1.on is a Stream 'end' event which doesn't have the standard callback argument signature of (err, results), this probably won't work. In that case you should just go with Promise.
With Promise you'll need to first Promisify and then join
var reader1Promise = Promise.promisify(reader1.on)('end');
var reader2Promise = Promise.promisify(reader2.on)('end');
var reader12Promise = Promise.join(reader1Promise, reader1Promise);
reader12Promise.then(function(){
doSomething();
});

Is there a better way to execute a node.js callback at regular intervals than setInterval?

I have a node.js script that writes a stream to an array like this:
var tempCrossSection = [];
stream.on('data', function(data) {
tempCrossSection.push(data);
});
and another callback that empties the array and does some processing on the data like this:
var crossSection = [];
setInterval(function() {
crossSection = tempCrossSection;
tempCrossSection = [];
someOtherFunction(crossSection, function(data) {
console.log(data);
}
}, 30000);
For the most part this works, but sometimes the setInterval callback will execute more than once in a 30000ms interval (and it is not a queued call sitting on the event loop). I have also done this as a cronJob with same results. I am wondering if there is a way to ensure that setInterval executes only once per 30000ms. Perhaps there is a better solution altogether. Thanks.
When you have something async, you should use setTimeout instead, otherwise if the asynchonous function takes to long you'll end up with issues.
var crossSection = [];
setTimeout(function someFunction () {
crossSection = tempCrossSection;
tempCrossSection = [];
someOtherFunction(crossSection, function(data) {
console.log(data);
setTimeout(someFunction, 30000);
}
}, 30000);
Timers in javascript are not as reliable as many think. It sounds like you found that out already! The key is to measure the time elapsed since the last invocation of the timer's callback to decide if you should run in this cycle or not.
See http://www.sitepoint.com/creating-accurate-timers-in-javascript/
The ultimate goal there was to build a timer that fires, say every second (higher precision than your timeout value), that then decides if it is going to fire your function.

Resources