setInterval 'stacking' up [duplicate] - javascript

This question already has answers here:
javascript animation queueing when page does not have focus
(3 answers)
Closed 8 years ago.
Using setInterval to run a function which gives a 'flash' effect to a list.
If I keep the page open, but visit another tab / come back in 10 minutes or so, the setInterval feels like its working every 1 seconds as the function is constantly being called.
Feels to me like its stacking up over time, anyway to fix this?
function flashListItems(){
$('.imageview_navigation li').each(function(i) {
$(this).delay((i++) * 100).fadeTo(200, 0.8).fadeTo(200, 1);
});
}
setInterval(function(){
flashListItems();
}, 10000);
fiddle: http://jsfiddle.net/6w6wrsm0/

There's nothing wrong with your code, some web browers slow these types of intervals down to not cause too much usage. So when the webpage is not used, the fastest a interval can go is usually about 1 sec.
There might be a way to fix this, which is mentioned here:
How can I make setInterval also work when a tab is inactive in Chrome?
Just make your animation function tick by real elapsed time.
var div = $('#my-div');
var leftValue = 0;
var interval = (1000/20); //20fps
var before = new Date();
setInterval(function()
{
now = new Date();
var elapsedTime = (now.getTime() - before.getTime());
if(elapsedTime > interval)
{
//Recover the motion lost while inactive.
leftValue += Math.floor(elapsedTime/interval);
}
else
{
leftValue++;
}
div.css("left", leftValue);
before = new Date();
}, interval);

Related

setInterval incrementally faster [duplicate]

This question already has answers here:
Changing the interval of SetInterval while it's running
(17 answers)
Closed 5 years ago.
Given a setInterval, can its timer keep getting quicker?
Such as that the code to be ran starts at 2 seconds, then 1.9s, 1.8s, 1.7s, etc...? (at this point I'm not worried about reaching zero or negative.)
I currently have:
let speed = 2000;
let timer = setInterval(function() {
display();
faster();
console.log(speed)
}, speed);
function faster() {
speed -= 100;
}
function display(){
// displays another square on canvas
}
I ask if it is possible because the console.log shows that the speed does indeed decrease, but the display function is not being called at faster intervals; it is always being called every 2 seconds. Therefor the speed of the setInterval is not getting faster....
No. The setInterval() rate is fixed at the value of the second argument when the timer is started.
You can use setTimeout() instead, reestablishing the timer upon each invocation of the callback:
var rate = 100;
setTimeout(function callback() {
// do something
setTimeout(callback, rate - 10);
});

If Element Hasn't Changed in the last 'X' Seconds

I have an element #ChatStatus which is constantly changing, and when a change occurs, the element slides in being visible on screen.
What I'm trying to do now is: If there hasn't occurred any changes on this element for the last 5 seconds for example, hide the element back out of the screen. Here's my code:
$('#ChatStatus').on("DOMSubtreeModified",function(){
$('#ChatStatus').animate({'right':'30px'},500);
});
// Now I wanna run this, when the #ChatStatus is innactive, or no changes occurred
// $('#ChatStatus').animate({'right':'-200vw'},500);
Here's the full project where I want to implement this inactivity feature.
https://jsfiddle.net/shuffledPixels/77hb2do0/1/
Here is a very functional way of doing it. As your commenters have mentioned, this really isn't the best way of doing it; but if you want to, it's your code.
shouldRemove = null;
$('#ChatStatus').on("DOMSubtreeModified",function(){
clearTimeout(shouldRemove);
$(this).animate({'right':'30px'},500);
shouldRemove = setTimeout(function () {
$(this).animate({'right':'-200vw'},500);
}.bind(this), 5000);
});
I am not very experienced with JS animation and the like, so I'll leave any question of style and method choice up to you. Aside from that, I would suggest using a global variable holding the time of the last change, and polling at regular intervals to see if that time is more than 5 seconds ago. For example:
var lasttime = none
$('#ChatStatus').change(function () {
lasttime = new Date().getTime() //Set lasttime to the time when the element changed
}
setInterval(function () {
if ((new Date().getTime() - lasttime) > 5000) { //Date().getTime() is in miliseconds,
// so 5000 for five seconds
$('#ChatStatus').animate({'right':'-200vw'},500);
}
}, 1000); // Set 1000 (1 second) lower for more precision at the
// cost of more computational time
I hope this helps!

Simple timer, and setinterval

What's the best way to create a timer in JS?
I've been using this so far:
var sec = 0;
setInterval(function (){sec +=1}, 1000);
I've noticed that, when I need miliseconds, it slows down by a lot. On browser tab changes, it completely stops.
var milisec = 0;
setInterval(function (){milisec +=1}, 1);
I'm looking for a better way to handle this, which will also continue to work when the browser window is changed.
With milliseconds, the resolution of the timer isn't large enough. In most cases the callback won't be called more often than roughly 50 to 250 times per second, even when you set the interval to 1ms. See Timer resolution in browsers (as referred to by Sani Huttunen) for an explanation.
With 1000ms it will work better. But still the timer won't be fired when the tab is inactive, and may be delayed when the cpu is busy or another script is running on your page.
One solution is to not increment a counter, but to test how much time has actually passed since the previous call of the timer. That way, the timing remains accurate, even when the intervals have been delayed or paused inbetween.
This snippet will remember the start date, and on each timer interval, update seconds and milliseconds to the difference between the current time and the start time.
var start = new Date();
var milliseconds = 0;
var seconds = 0;
setInterval(function()
{
var now = new Date();
milliseconds = now.getTime() - start.getTime();
seconds = round(milliseconds / 1000);
}, 1000);
I've set the interval to 1000 again. You might set it shorter, but it will cost more performance.
Related question: How can I make setInterval also work when a tab is inactive in Chrome?
Based on #goleztrol's solution, I've created an alternate solution specifically for my situation (it might not work for everyone).
I just ask the exact time when it's needed with this function, to know the exact miliseconds passed:
var start = new Date();
var msPassed = function() {
var now = new Date();
var ms = now.getTime() - start.getTime();
return ms
}
msPassed(); //returns time passed in ms
I needed to position objects (on creation) depending on how much time passed until their creation, so for my case this is a perfect solution. However, my initial question asks for the perfect timer, and this is not it. Anyway, here it is for future reference.

window.setTimeout behaviour when window not in focus [duplicate]

This question already has answers here:
How do browsers pause/change Javascript when tab or window is not active?
(3 answers)
Closed 9 years ago.
Here's the simplest code for reproducing I could think of:
ms = 30; // 1000 ?
num = 1;
function test()
{
num+=ms;
document.getElementById('Submit').value = num; // Using native Javascript on purpose
if (num < 4000)
window.setTimeout(test, ms);
}
test()
I set the ms (milliseconds between iterations) to 30, ran the script and moved to different tab on the browser.
Then I wait for about 10 seconds (the script should finish within 4 seconds) and came back to the tab.
If I used Firefox I saw that the script has not finished, and the numbers are still running (resuming from where I left them, I guess).
Which is annoying enough,
But if I changed ms to 1000 and repeat the above steps, when I come back to the tab I saw the script has indeed already finished.
(The script should still take 4 seconds to finish).
Namely, sometimes Firefox runs window.setTimeout even if the window is out of focus, and sometimes it doesn't. Possibly depending on the duration
On the other hand, this is not happening with Internet Explorer.
It keeps running the script even if the tab is not focused. No matter how I set the ms.
Is that due to some performance considerations of Firefox?
What exactly is happening?
How come such a basic thing is in consistent between browsers,
nowadays?
OR, am I working wrong? Is it a weird way for coding?
I'm just trying repeatedly change the DOM, in a delayed fashion, without using setInterval (because I'm changing the interval it self on the go).
And most important, how should I regard this?
I can't assume my user won't leave the tab.
I want to allow my user to leave the page for as mush as one might like.
If one leaves and come back after half an hour, he/she will see irrelevant animations on the page, still running.
Some of these animations are seen by all the users connecting to the page.
There is no need they will be synchronized in resolution of milliseconds, but I can't start them only when the user put the tab/window in focus.
I'm using Firefox 25.0.1, and IE 11. (Windows 7)
Most modern browsers (especially on mobile devices) suspend execution of scripts in tabs that are out of focus to save CPU cycles (for instance, this is why requestAnimationFrame was brought to life). In the case of timeouts, shorter intervals are actually changed to a different / higher value as the browser vendor sees fit.
What you can do to overcome this (if you really must know the interval between successive executions) is to set a timestamp when the timeout is activated, and compare it with the timestamp when the timeout handler is actually executed. Note that when you're animating it's best to calculate properties of the animated Objects by taking other application variables into account, rather than rely on the amount of calls a particular handler has had.
You could also attach listeners to the window for "(un)focus" Events to know when the user has "come back" to your application. In this event handler you can verify whether a timeout was pending and execute its callback manually, if you must do so.
see the difference: http://jsfiddle.net/qN6eB/
ms = 30; // 1000 ?
num = 1;
start = new Date();
function test()
{
num+=ms;
document.getElementById('Submit').value = num;
if (num < 4000)
window.setTimeout(test, ms);
else
document.getElementById('Time').value = new Date() - start;
}
test()
ms2 = 30; // 1000 ?
num2 = 1;
start2 = new Date();
dueTo = new Date(+new Date()+4000);
function test2()
{
num2+=ms2;
document.getElementById('Submit2').value = num2;
if (new Date() < dueTo)
window.setTimeout(test2, ms2);
else
document.getElementById('Time2').value = new Date() - start2;
}
test2()
setTimeout is not precise for timing. Because the timer doesn't interrupt the process, I'll wait for idle time. I don't know how the browsers are managing it, but an inactive tab probably has a lower priority.
I can think about two solutions :
- Try setInterval (I'm not sure if this will solve your problem or not)
- Instead of incrementing a variable, use a Date object, containing the time at the beginning, and compare it with the current time when the function is executed.
var beginTime = (new Date()).getTime();
var intervalId = setInterval(function() {
var timePassed = (new Date()).getTime() - beginTime;
document.getElementById('Submit').value = timePassed;
if(timePassed >= 4000) {
clearInterval(intervalId);
}
}, 30);

ajax/JS timed countdown?

Let me explain what I'm trying to do.
I want to make a simple box which counts down numbers at intervals I specify.
For example, I'd like to set it to start at 150, and then I want to set it to drop by 15 every 30 seconds.
Is this possible with AJAX/Javascript? If so, could someone point me in the right direction?
Would really appreciate any help on this script, been Googling for hours now! :(
Cheers
Kieran
Have a look at the setTimeout or setInterval methods, they allow you to execute a function after a specified number of milliseconds (1000ms = 1second). Use that, to call a function that keeps dropping the number and writes it to a HTML element to the user can see it.
this isn't tested, but i hope it shows you the way to go.
var start = 150;
var drop = 15;
var interval = 30;
function countdown(){
document.getElementById('mybox').innerHTML = start;
start-=drop;
window.setTimeout("countdown",interval*1000);
}
countdown();
You may use jQuery to do that, see http://keith-wood.name/countdown.html -> tab Callbacks
Keep in mind that 30 seconds in my browser are not necessarily equal to 30 seconds in your browser. It depends on the workload of the browser.
The time difference is minor for a short time but can increase over a long time. The times will drift apart. If the times must not be equal (or nearly equal) between two visitors than such simple solution should be fine.
We had once a problem to introduce a live clock / countdown in one of our projects. We build a script with javascript, ajax and PHP for clock synchronisation (server time was timeserver).
You should use setInterval / clearInterval which is made for this kind of tasks:
function cooldown(element, start, stop, step, delay) {
var current = start;
element.innerHTML = current;
var timer = setInterval(function () {
current -= step;
if(current < stop) current=stop;
element.innerHTML = current;
if(current == stop) clearInterval(timer);
}, delay*1000);
}
Demonstrated here : http://jsfiddle.net/PCMHn/

Categories