Javascript SetInterval timing issue, total time - javascript

base ={time:0};
var loop = 0;
setInterval(function(){
if(base.time === 9000){
move();
base.time = 0;
}
base.time ++;
},1);
Shouldn't the move(); function occur every 9s? I timed it and its much less, why is that?

setInterval will not run every millisecond. There is a minimum possible interval that is longer than that.
If you want something to run in nine seconds, you should use setTimeout() for 9 seconds. Plus your code doesn't reset base.time back to zero so it would only match 9000 once anyway.
If you want it to run every 9 seconds, then you can use setInterval(handler, 9000) or you can use setTimeout(handler, 9000) and then set the next setTimeout in your handler function.
This will execute move() every nine seconds:
var intervalTimer = setInterval(function(){
move();
}, 9000);
Here's a useful article on the topic: http://www.adequatelygood.com/2010/2/Minimum-Timer-Intervals-in-JavaScript.
To reset the time back to 9 seconds when a button is clicked use this code:
var intervalTimer;
function startTimer() {
intervalTimer = setInterval(function(){
move();
}, 9000);
}
function handleClick() {
clearInterval(intervalTimer); // stop currently running interval
startTimer();
}
startTimer();
See it in action here: http://jsfiddle.net/jfriend00/sF2by/.

Intervals are easy as pie!
var move = function(){
alert("move!");
};
setInterval(move, 9000);
See it work here on jsFiddle

You can't count on setInterval actually running every 1 ms. If the CPU is used for another process, it might not run for 1 second. Instead, use one of the following:
function move() {
// Do stuff.
}
// The obvious solution.
// Certain browsers (Chrome) may put the script in "inactive" mode which will
// pause setInterval code. This means move will be run too few times, if you
// actually depend on it being called X times for Y time.
setInterval(move, 9000);
// The other solution.
// Get the delta between each loop and run the move loop as necessary.
// WARNING: This is not efficient, and you should only use this if you have a
// good reason to do so.
// EXTRA WARNING: This code is actually retarded in its current form. It's just
// here to show you how you'd do it. Since you didn't post your
// original problem, it's hard to know what you're really after.
var time = +new Date, frequency = 9000;
setInterval(function () {
var dt = new Date - time;
// Check if we've waited long enough.
if (dt >= frequency) {
// If the process hangs for 20 seconds, this value would be 2. Usually,
// it will be 1.
// Also, Chrome will pause interval counters, so if a tab is inactive,
// this count could be really high when the tab gets focus again.
var times = Math.floor(dt / frequency);
console.log('Moving', times, 'time(s)!');
for (var i = 0; i < times; i++) {
move();
}
// Start counting time from the last update.
time += times * frequency;
}
}, 1); // 1 could probably be much higher here. Depends on your use case.

You wrote in a comment that there is a button which resets the time, and that's why you don't want to just setTimeout for the full delay. Here's how to handle that:
var running;
function start() {
clearInterval(running);
running = clearInterval(function () {
move();
}, 9000);
}
Every time start() is called, the time will be reset to 9 seconds from now, and if 9 seconds elapse, move() will be called and another 9-second interval will start. If you don't actually want it to happen repeatedly, just use setTimeout instead.
The key is using clearInterval (or clearTimeout) to cancel your previous 9-second-delay and start a new one. It is harmless to call clearInterval with a junk value.

Related

function executed by setInterval() multiple doesn't show results | Javascript

I am making a timer in javascript. But there is one thing I am not getting.
Here's the code...
var time = 0;
var timeInterval;
var testTime;
//Main code which increases the value of variable time by 1 every second until interval is stopped
timeInterval = setInterval(function (){
time++;
testTime = time;
}, 1000);
//Code to stop the interval after 10 seconds.
setTimeOut(function() {
clearInterval(timeInterval);
},10000);
//Expected value -> 10
//I get -> 0
console.log(testTime)
If I am running a function which increases the value of time by 1 10times by setInterval() method... Why the value of time is not updating?
When you call setInterval, you are asking code to run after a certain amount of time. The setInterval function is an example of a function that takes a function as a parameter.
This means that you're declaring a function and asking setInterval to call it at a later time all in one go. None of what is inside the function will be called until the interval happens.
Your console.log is not inside either of the functions you gave to setInterval or setTimeout, so it will run straight away.
The order of execution is:
Your variables are declared
Your call to ask setInterval to run your function periodically
Your call to ask setTimeout to run your function after 10 seconds
Your console.log is made
At this point, the execution on your main thread ends
The function you gave to setInterval is called a bunch of times
The function you gave to setTimeout is called once
If you want to fix your code, you can put the console.log in the setTimeout function to ask it to run at the end of the 10 seconds (putting it inside step 7).
var time = 0;
// Main code which increases the value of variable time by 1 every second until interval is stopped
var timeInterval = setInterval(function (){
time++;
console.log("time during interval: ", time);
}, 1000);
// Code to stop the interval after 10 seconds.
setTimeout(function() {
clearInterval(timeInterval);
console.log("time at end: ", time);
}, 10000);
Depending on your objective, you might rather simplify your code by calling clearInterval inside your interval function (if(time > 10) clearInterval(...)) to reduce the likelihood of a bug.

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!

Concurrent actions with setInterval and setTimeout

I'm a JavaScript newbie and I'm trying to achieve concurrent actions with setInterval and setTimeout.
What I'd like to achieve, what actually happens and what I expected to happen is best explained with the following code.
var myVar = setInterval(function() {
myTimer()
}, 1000);
function myTimer() {
var d = new Date();
var t = d.toLocaleTimeString();
document.getElementById("demo").innerHTML = t;
}
for (var i = 0; i < 100; i++) {
setTimeout(function() {
console.log("log " + i);
}, 3000);
}
<p>A script on this page starts this clock:</p>
<p id="demo"></p>
My expectation for the leading setInterval, is that the function myTimer is executed every second, independent of what happens afterwards. Except of course if the site is closed or clearTimeout is called on the myVar.
I can not verify if this action really happens independently and in an ongoing manner.
The following for loop, is there to simulate further code, to see if the myTimer function would be executed independently.
I expected the loop to start with i=0, then wait for three seconds, log log 0 to the console, then continue with i=1 and so on.
Instead it appears that the timeout is started and in the meantime i has reached the end of the for loop and is therefore 100.
How do I get the for loop to wait with the iteration for the setTimeout?
And is the setInterval really executed every second, independent of the following code? E.g. if the following code had actions that take some processing/time, would the clock update anyways, during the processing?
You could change the timeout time with the factor of i and use a closure over i to get the right value.
function myTimer() {
var d = new Date();
var t = d.toLocaleTimeString();
document.getElementById("demo").innerHTML = t;
}
var i,
myVar = setInterval(myTimer, 1000);
for (i = 0; i < 100; i++) {
setTimeout(function (i) {
return function() {
console.log("log " + i);
};
}(i), 3000 * i);
}
<p>A script on this page starts this clock:</p>
<p id="demo"></p>
A version with calling timeout after timeout.
function myTimer() {
var d = new Date();
var t = d.toLocaleTimeString();
document.getElementById("demo").innerHTML = t;
}
function next() {
i++;
console.log("log " + i);
if (i < 300) {
setTimeout(next, 3000);
}
}
var i = 0,
myVar = setInterval(myTimer, 1000);
setTimeout(next, 3000);
<p>A script on this page starts this clock:</p>
<p id="demo"></p>
About your setInterval question, yes. It will run every second (not being millisecond scrupulous). let's say you just set your setInterval, and then run an action that takes half a second to run. The interval will count that half second and run after another half second. Hard code will not delay the clock, BUT, if you are running code just in the moment that the interval should fire, it will wait for that code to end, as JavaScript is single threaded. This means that if right after setting your interval you run code that lasts more than 1 second, the interval callback will be ran after it, so it will not be fired in 1 second. By the way, subsequent interval calls will be called not after this interval, but after the interval was set. Check this fiddle (F12): https://jsfiddle.net/0gggmemu/4/
You see that the first interval is called when the code ends, but subsequent intervals are called counting when the interval was set (check milliseconds, how they fit the first log instead of the start one). Note that the intervals are not stacked. If it should have called 10 intervals, it will only call one and wait for the next. If time precision is important for you, then you should save a reference at startup and check the difference in each interval.
About concurrency, the same as when you call setInterval, when you call setTimeout the code will continue its execution, creating a hundred of timeouts at the same time. If you want code to hang just check my fiddle. By the way, if your worry is about setTimeout locking setInterval, don't worry, as the code will not be blocked. You only have to semi-worry if you have code that gets stuck somewhere, but in a callback-driven application is kinda difficult to achieve this.

How to cancel out a setTimeout function?

I am making a boon system where the player gets a random boon/buff for 30 seconds and then it removes itself. I have the initial boon in place where it lasts 30 seconds, then removes itself. I push the boon name "Healing Boon" to a empty player.boons = [] array.
However I am running into difficulty the other way around. Lets say the enemy wants to "debuff" my character, and REMOVE the boon instantly. Well because the countdown for my boon lasts 30 seconds, it continues to work until the 30 seconds is up, even if I give the appearance of removal. (I still keep gaining health up to 30 seconds).
I am attributing this to the setTimeout function. If I input 30 seconds, even if later down the line (say 5-10 seconds later), make setTimeout = 0; it will still continue on for the next 30 seconds. It is only on the initial 2nd attempt is setTimeout set to 0. But this is not what I want. I want a system that stops the boon entirely in its tracts and removes any current health buffs it gives the player.
function applyBoonHealing(){
var blessedWind = setInterval(function(){
player.cc.hp += 1;
dom.setText("healthcounter", player.cc.hp);
}, 1000);
player.boons.push("Healing Boon");
postPlayerStatusEffectImage("images/lowerstrengthicon.jpg", "buff", "0", "2", "no");
dom.setText("healthcounter", player.cc.hp);
setTimeout(clearBoon, 30000);
function clearBoon(){
clearInterval(blessedWind);
if (player.boons.includes("Healing Boon", 0)){
var arrayIndex = player.boons.indexOf("Healing Boon", 0);
player.boons.splice(arrayIndex, 1);
}
dom.setText("healthcounter", player.cc.hp);
postPlayerStatusEffectImage("images/lowerstrengthicon.jpg", "buff", "0", "2", "yes");
}
}
clearTimeout() method is solution to this problem:
var boonHandle = setTimeout(clearBoon, 30000);
(...)
clearTimeout(boonHandle); //To cancel your timer
you can use clearTimeout() method,
var mySetTimeoutFunc = setTimeout(clearBoon, 30000);
to stop this you will just have to clearTimeout(mySetTimeoutFunc);
for more info see this http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_win_settimeout_cleartimeout2
clearTimeout is a event to stop Timeout, see below
function myStopFunction() {
clearTimeout(myVar);
}

Javascript countdown is going slow?

I'm trying to make a countdown that is counting down in milliseconds; however, the countdown actually takes much longer than 7 seconds. Any idea as to why?
function countDown(time){
var i = 0;
var interval = setInterval(function(){
i++;
if(i > time){
clearInterval(interval);
}else{
//mining
$('#mining_time').text($('#mining_time').text()-1);
}
}, 1);
}
And I can confirm the varible time passed to the function is correctly set to 7000.
For a mostly-accurate countdown, use setTimeout().
setTimeout(fn, 7e3);
If you absolutely must have it as close to 7 seconds as possible, use a tight poll (requestAnimationFrame()) and look at difference between the time of start and current poll.
var startTime = Date.now();
requestAnimationFrame(function me() {
var deltaTime = Date.now() - startTime;
if (deltaTime >= 7e3) {
fn();
} else {
requestAnimationFrame(me);
}
});
Poly-fill as required.
the most precise way to run something after 7 seconds - is to use setTimeout with 7000 ms interval
a. there is no browser that guarantees an interval to run with 1ms resolution. In the best case it would be 7-10ms
b. there is only one thread in js, so the tasks are queued. It means that the next run will be scheduled to only after the current run is finished.
Some useful reading: http://ejohn.org/blog/how-javascript-timers-work/
No browser will take 1 as parameter for setInterval. Off the top of my head the minimum is 4 ms.
For an accurate result, get the current time, add 7000 ms, and poll (using setInterval or setTimeout) until you reach that new time.
A quick Web search returned this article that provides an example.
[Update] the value of 4 ms is mentioned on this MDN page.

Categories