Periodically call node.js function every second - javascript

I have a node.js server and client. The client has a video.js player, progressbar.js and socket.io. I want progressbars to show buffer percentage of other users.
Here is piece of server source
function updateProgressBars() {
io.sockets.emit('updateProgressBars'); //Send data to everyone
}
socket.on('userProgressBarUpdate',
function(data) {
socket.broadcast.emit('changeLocalProgressBar', data); //Send data to everyone but not sender
});
And here is client
socket.on('updateProgressBars',
function() {
var bufferLevel = myPlayer.bufferedPercent();
var data = {
bl: bufferLevel,
n: name
}
socket.emit('userProgressBarUpdate', data); //Send data to server
});
changeLocalProgressBarLevel is just changing progressbars on client side so dont worry about it.
How can I make updateProgressBars() be called every second.

You can use setInterval(function(){ ... }, timeMiliSeconds)
setInterval(function(){ console.log("hi")},1000) //logs hi every second

using setInterval is not the best choise because you should always clearInterval. I prefer using recursion with bluebird promises:
function a()
{
if(smthCompleted)
dosmth();
else return Promise.delay(1000).then(() => a());
}
This way you have much better control of your code.

You can achieve this by using f.e. the "setInterval" function.
function doStuff() {
//do Stuff here
}
setInterval(doStuff, 1000); //time is in ms
And even better:
let myVar = setInterval(function(){ timer() }, 1000);
function timer() {
//do stuff here
}
function stopFunction() {
clearInterval(myVar);
}

Related

NodeJS / jQuery - Poll notifications API

I have the following JSON data in an API:
[
{
notification: "'James' has created a new user. This requires
approval",
read: null
}
]
I have the following jQuery:
$.ajax({
dataType: "json",
url: "/api/notifications",
success: function(data) {
counterText = 0;
$.each(data, function(index, value) {
if(value.read == 0 || value.read == null)
{
var theCounter = parseInt($('.counter').text());
counterText += theCounter += 1;
}
});
$('.counter').text(counterText);
}
});
The problem is that this only works when someone refreshes the browser. I am using Socket.io in order to do real-time notifications, however, instead of each notification coming in, I just ideally need to update this code each time a socket comes in. For example, an event called "Ping"
socket.on("test-channel:App\\Events\\Ping", function(message) {
$.toast({
heading: 'Information',
text: message.data.message,
icon: 'info',
loader: false, // Change it to false to disable loader
loaderBg: '#9EC600' // To change the background
});
});
There are, however, a lot of events so I don't really want to have to update on each on. Ideally, I would like instant polling on this file so that notifications can updated immediately without the need of refreshing the browser.
To paraphrase, it sounds like you'd like to add a polling mechanism to your AJAX approach. (Sockets can have advantages such as reduced latency, but they can be slightly more complex, so I understand why you may not want to try them at this time.) All your current AJAX code lacks is really just a mechanism to make continual requests on an interval. You can do that with:
var polling = true;
var period = 60 * 1000; // every 60 seconds
var interval = polling && setInterval(function() {
if (polling) {
$.ajax({
... // existing ajax call here
});
} else {
if (interval) {
clearInterval(interval);
}
}
}, period);
// Later, if you want to stop polling, you can:
polling = false;
// ...or even just:
if (interval) {
clearInterval(interval);
}

how to design an elegant js polling routine?

I have a requirement where I need to poll the database via ajax from js to check for a status. If the status is "active" then the polling should stop and an alert should popup "case is now active". The js should check the db every 2 seconds until the db status returns "active." Can you provide an elegant js routine for this? Here's some general js to show what I want to do:
function ReportAsActivePoll()
{
for(var i=0; i<10; i++)
{
setTimeout(StatusIsActive,(i*2000));
if(statusIsActive)
{
ReportAsActive();
break;
}
}
}
var statusIsActive = false;
function StatusIsActive(case)
{
statusIsActive = GetStatusFromDB(case) == "active";
}
function ReportAsActive()
{
alert("case is now active")
}
A few notes:
I know the code above is not correct. It's just for illustrative purposes.
The code above will call StatusIsActive 10 times. I would like the calls to stop/break/discontinue after status is active. However, I think polling requires to queue up all the calls ahead of time so I'm not sure how to achieve this.
Use setInterval() and clearInterval() for simplicity. Like so:
<script type="text/javascript">
function checkStatus(theCase) {
var intervalId = window.setInterval(function() {
if (getStatusFromDb(theCase) == 'active') {
clearInterval(intervalId)
reportAsActive()
}
}, 2000)
}
function reportAsActive()
{
alert("case is now active")
}
var tmpCounter = 0
function getStatusFromDb(theCase)
{
if (tmpCounter++ == 4) return "active"
}
checkStatus('case 123')
</script>
You should also consider making functions start with a lowercase letter, because that is the normal JS convention. By choosing another style, you risk having case-sensitive errors that are annoying to track down.
You need to use setInterval instead of your setTimeout and when you received a valid response you have to remove this interval with clearInterval.
So you need to do something like this
var intervalID = window.setInterval(function(){
var resFromYourDB = ...; // get your result via ajax
if (resFromYourDB['active']){
window.clearInterval(intervalID);
// do you alert
}
}, 2000)
This way it will be polling your server till it will get active as a response and not a predefined amount of time as with setTimeout. Also when it will get this response it will properely stops.

Using setInterval with asynch functions that could take longer than the interval time

Is there a way to keep your asynch functions somewhat in order using setInterval? For instance, if you're doing some kind of IO connection and it takes longer than the interval time you set you get things a little off. I could increase the interval time to something that hopefully would cover it, but that's not sure fire enough.
The code looks like this:
var sqlID = setInterval(function(){
console.log('Attempting to reconnect to sql...');
dbHandler.connectSQL(sql, connStr, function(sqlconnect){
conn = sqlconnect;
if (conn != false){
clearInterval(sqlID);
}
});
}, 10000);
If you want them queued, wihtout Promises/Deferreds you can do:
function tryToConnectIn10Seconds(){
setTimeout(function(){
console.log('Attempting to reconnect to sql...');
dbHandler.connectSQL(sql, connStr, function(sqlconnect){
conn = sqlconnect;
if (conn != false){
//Done. Do something with conn
}else{
tryToConnectIn10Seconds();
}
});
}, 10000);
}
Cheers

Why is the JavaScript console saying my variable is undefined, even when I defined it two lines before?

I'm using WebSockets to connect to a remote host, and whenever I populate realData and pass it to grapher(), the JavaScript console keeps telling me realDatais undefined. I tried checking the type of the data in the array, but it seems to be fine. I've called grapher() before using an array with random data, and the call went through without any problems. With the data from the WebSocket, however, the call will always give me "error: realData is not defined". I'm not sure why this is happening. Here is the code I used:
current.html:
var command = "Hi Scott"
getData();
function getData()
{
console.log("getData is called");
if("WebSocket" in window)
{
var dataCollector = new WebSocket("ws://console.sb2.orbit-lab.org:6100",'binary');
dataCollector.binaryType = "arraybuffer";
console.log(dataCollector.readyState);
dataCollector.onopen = function()
{
//alert("The WebSocket is now open!");
console.log("Ready state in onopen is: " + dataCollector.readyState);
dataCollector.send(command);
console.log(command + " sent");
}
dataCollector.onmessage = function(evt)
{
console.log("onmessage is being called");
var realData = new Uint8Array(evt.data);
console.log(realData);
grapher(realData); //everything up to this point works perfectly.
}
dataCollector.onclose = function()
{
alert("Connection to Server has been closed");
}
return (dataCollector);
}
else
{
alert("Your browser does not support WebSockets!");
}
}
graphing.js:
function grapher(realData)
{
console.log("grapher is called");
setInterval('myGraph(realData);',1000); //This is where the error is. I always get "realData is not defined".
}
function myGraph(realData)
{
/*
for(var i = 0; i < SAarray.length; i++) // Loop which will load the channel data from the SA objects into the data array for graphing.
{
var data[i] = SAarray[i];
}
*/
console.log("myGraph is called");
var bar = new RGraph.Bar('channelStatus', realData);
bar.Set('labels', ['1','2','3','4','5','6','7','8']);
bar.Set('gutter.left', 50);
bar.Set('gutter.bottom', 40);
bar.Set('ymax',100);
bar.Set('ymin',0);
bar.Set('scale.decimals',1);
bar.Set('title','Channel Status');
bar.Set('title.yaxis','Status (1 is on, 0 is off)');
bar.Set('title.xaxis','Channel Number');
bar.Set('title.xaxis.pos',.1);
bar.Set('background.color','white');
bar.Set('colors', ['Gradient(#a33:red)']);
bar.Set('colors', ['red']);
bar.Set('key',['Occupied','Unoccupied']);
bar.getShapeByX(2).Set('colors',barColor(data[0]));
bar.Draw();
}
Because strings (as code) passed to setInterval execute in the global scope, therefore the realData parameter isn't available. There's rarely a good reason to pass a string to setInterval. Instead, use:
setInterval(function () {
myGraph(realData);
}, 1000);
Reference:
https://developer.mozilla.org/en-US/docs/Web/API/window.setInterval
Try it without it needing to evaluate a string:
setInterval(function() {
myGraph(realData);
},1000);
Any time you are using setTimeout or setInterval, you should opt for passing an actual function instead of a string.

Javascript processes already running then wait

I can't get a function to work. It should check if Iexplore.exe is running, if it's running then wait. If not then run the Script.
I'm not sure how to add wait function in.
function main() {
var ieinfostate = false;
var iewait = setInterval(function () {
if (ProcessesRunning("iexplore.exe") != 1) {
clearInterval(iewait);
dosomethingelse();
} else if (ieinfostate == false) {
Javascript in a browser does not have a wait function and there is no way to make one.
In your particular case, you could use a setInterval() call to regularly check some state every 500ms or so and then when you find the desired state, stop the interval timer and carry out some action.
var timer = setInterval(function() {
if (ProcessesRunning ("iexplore.exe") == 1) {
server.logMessage( "Please close Internet explore first" );
} else {
clearInterval(timer);
var shell = new ActiveXObject( "WScript.Shell" );
server.logMessage( "Unpacking file" );
// ...
}
}, 500);
since you are using jscript, there is a sleep() method. thought.. thats the worst you could use since javascript is designed to be async.
you could do it like this:
var ieinfostate = false;
var iewait = setInterval(function () {
if (ProcessesRunning("iexplore.exe") != 1) {
clearInterval(iewait);
dosomethingelse();
} else if (ieinfostate == false) {
ieinfostate = true;
server.logMessage("Please close Internet Explorer first. This installer will wait till its closed.");
}
}, 500);
var dosomethingelse = function () {
var shell = new ActiveXObject("WScript.Shell");
server.logMessage("Unpacking file");
/* your unpack stuff here */
};
sadly a timer is the only way to wait for closing of a process in windows.
microsoft fails hard at implementing usefull api's like process state change events etc in jscript.
if you would like to have it clean you should consider using c, c++ or c#

Categories