I have multiple countdown timers in my app and I'm updating those values using setInterval function. The idea of following code block is the loop through all ongoing games and update countdown clocks. I have 1000ms interval but it loops much faster than that. Why? When I open multiple browser windows to see countdown timer updates I can notice that interval is something like 500ms.
if (Meteor.isClient) {
Meteor.setInterval(
function() {
var going = Games.find({isGoing: true});
var goingFetch = going.fetch();
var goingCount = going.count();
for (i = 0; i < goingCount; i++) {
Games.update(goingFetch[i]._id, {$set: {timeLeft: goingFetch[i].timeLeft - 1}});
}
}
, 1000 );
}
Is there better way to solve this problem? I may have 100 games simultaneously and every game have one to many timers. Timer type can be countdown or incremental and all timers are stoppable. Interval is always and in all cases 1000ms.
UPDATE
I did more tests and setInterval works fine but clients still have too fast countdown timer.
Are you sure your code isn't executed twice by mistake? Does goingCount produce correct results, for instance? setInterval isn't as accurate as setTimeout, but it shouldn't cause problems at 1000ms. Can we see more of your code?
Related
I'm building a live chess app, and I'm trying to add a timer to it. However, I am struggling to find a way to make the timer accurate. I have run some tests, and setInterval and setTimeout are extremely inaccurate, with a ten minute timeout being off by over three minutes. I also tried using setInterval with in interval of 100ms, but even that was off by over minute, when the tab was not active. That was just with the javascript window.setInterval; with nodejs, it hasn't been more than 10ms off, but I'm afraid it will if the server gets busy. I'm hoping to find a way to have the game end within at least a tenth of a second of the real time.
Any suggestions? Thanks!
an ideal approach would be to use absolute clock time to get time elapsed and timer to have that check.
Something like code below.
const startTime = new Date();
const maxTime = 5 * 1000; // 60 seconds
setInterval(() => {
checkExpired();
}, 300);
function checkExpired() {
const curTime = new Date();
timeDifference = Math.abs(curTime.getTime() - startTime.getTime());
if (timeDifference > maxTime) {
console.log("time up");
}
}
The browser will not run setInterval as required due to performance reason.
https://usefulangle.com/post/280/settimeout-setinterval-on-inactive-tab
If you need to run timer with required interval then it can be run in worker thread.
some info here.
How can I make setInterval also work when a tab is inactive in Chrome?
But my guess is increased granularity is fine for non active tab.
I have a little script that runs a simulation, of which I want to render the results 'live':
for ( i < simulation steps ) {
do_simulation();
render_with_flot();
}
I noticed that the plot only gets rendered after the last step.
Is there a way to 'suspend' javascript somehow to allow the rendering to run after each iteration?
Or is there a way to make flot run synchronously?
Or do I need to set my own timeouts for each iteration of the for-loop? This seems like kind of a hassle.
Depends how fast it needs to run, but the best way would be to use SetInterval
Pseudocode / hand-written-javascript-that-probably-doesnt-run:
var PerformedSteps;
var Interval;
PerformedSteps = 0;
Interval = setInterval(work, 1000/60); //60 times/second
function work()
{
PerformedSteps++;
if (PerformedSteps == simulation_steps)
{
clearInterval(Interval);
return;
}
do_simulation();
render_with_flot();
}
As an alternative to #PhonicUK's solution, you could do a setTimeout() at the end of work() to schedule the next call to work(), giving the rendering a chance to happen & not tying yourself to any particular refresh rate.
I'm pretty new to (javascript) programming and I'm trying to get something automated.
There is a page that contains a countdown timer, and I want my greasemonkey script to automatically do some actions if the condition is met.
I've got this right now:
var timer = document.getElementById('timer_4975');
if (timer.innerHTML < "00:00:20"){
//Some actions
}
But this only checks the condition once when the script is loaded, when the timer goes under 00:00:20, it doesn't detect the condition is met and doesn't go to action.
Can someone guide me in the right direction?
Thanx in advance!
You can use the setTimeout or setInterval functions to perform this task.
setInterval will perform a task regularly, which is probably more suited to what you want to achieve.
Something like:
var timer = document.getElementById('timer_4975');
var intervalHandle = setInterval(function() {
if (timer.innerHTML < "00:00:20"){
//Some actions
clearInterval(intervalHandle);
}
},1000);
would check every second (1000ms). Change the 1000 value to increase or decrease the frequency of checking... once a second is likely to be often enough.
You will have to use setInterval() to execute your code more than once:
setInterval(function() {
if(timer.innerHTML < "00:00:20") {
//Some actions
}
}, 5000); //Execute this function each 5 seconds.
Belive me i ve seen many solutions i still dont know why this doesnt work.
timerId = 0;
$("#dumpStartId").click(function(){
var proId = $("#curProfileId").val();
timerId = setInterval(function(){
showact();
showactdat();
},1000);
});
$("#dumpStopId").click(function(){
clearInterval(timerId);
document.getElementById('curSeqId').value = "";
if(timerId)
{
clearInterval(timerId);
}
});
dumpstartid and dumpstopid are the ids of the two buttons. Even after clicking stop the intervals are executing continuosly. Im not sure whats wrong with this code. No errors in the console too.
Update: I can observer that sometimes after insanely pressing the button for around 5 or 6 times it comes to a complete halt. Cant this thing stop instantaneously (or is too much to ask??)
setInterval iterates every "Millisecond-Value" you've given till it reaches the clearInterval. Try using onmousedown instead of onclick.
It was because the function the setInterval is calling was problematic which polls a rest service at a varied interval from the setIntervals interval causing it to conflict. I ve corrected it and that fixed it.
I have to use atleast 2 setTimeouts and 1 setInterval. Does this have any dependency on the browser or javascript engine being used?
tl;dr: Don't worry about the cost of timers until you're creating 100K's of them.
I just did a quick test of timer performance by creating this test file (creates 100K timers over and over):
<script>
var n = 0; // Counter used to verify all timers fire
function makeTimers() {
var start = Date.now();
for (var i = 0; i < 100000; i++, n++) {
setTimeout(hello, 5000);
}
console.log('Timers made in', Date.now() - start, 'msecs');
}
function hello() {
if (--n == 0) {
console.log('All timers fired');
makeTimers(); // Do it again!
}
}
setTimeout(makeTimers, 10000); // Wait a bit before starting test
</script>
I opened this file in Google Chrome (v54) on my circa ~2014 Macbook Pro, and went to the Timeline tab in Developer Tools and recorded the memory profile as the page loaded and ran thru 3-4 cycles of the test.
Observations
The timer creation loop takes 200ms. The page heap size starts at 3.5MB pre-test, and levels out at 3.9MB.
Conclusion
Each timer takes ~.002 msecs to set up, and adds about 35 bytes to the JS heap.
On a page you can have as many setTimeouts/setIntervals running at once as you wish, however in order to control each individually you will need to assign them to a variable.
var interval_1 = setInterval("callFunc1();",2000);
var interval_2 = setInterval("callFunc2();",1000);
clearInterval(interval_1);
The same code above applies to setTimeout, simply replacing the wording.
As Kevin has stated, JavaScript is indeed single threaded, so while you can have multiple timers ticking at once, only one can fire at any one time - i.e. if you have one that fires a function which 'halts' in execution, for example with an alert box, then that JS must be 'resumed' before another can trigger I believe.
One further example is given below. While the markup is not valid, it shows how timeouts work.
<html>
<body>
<script type="text/javascript">
function addThing(){
var newEle = document.createElement("div");
newEle.innerHTML = "Timer1 Tick";
document.body.appendChild(newEle);
}
var t1= setInterval("addThing();",1000);
var t2 = setInterval("alert('moo');",2000);
</script>
</body>
</html>
You can use as many as you want. Just remember that JavaScript is single threaded, so none of them can execute in parallel.
var interval_1 = setInterval("callFunc1();",2000); calls eval() which is evil so it's BAD.
Use this instead var interval_1 = setInterval(callFunc1,2000);
And for the question, you may use as many as you want but if all have the same interval between two actions, you better do it this way
var interval = setInterval(function() {
// function1
fct1();
// function2
fct2();
},2000);