javascript loop going mental - javascript

I have a simple javascript loop on my php page that just adds 1 to a value every second. Well, the loop runs every second, and increments the value.
var test = 0;
function go() {
test = test + 1;
setTimeout(go, 1000);
}
go();
This works fine.
Problem is, the PHP page this runs on is actually inside a div tag that refreshes every 10 seconds. After 10 seconds, the count goes haywire, adding 2 every second, then 3, then 4, etc.
How can I stop this?

Given that the problem appears to be multiple instances of your function running, increasing on each refresh/update of the page, I'd suggest adding a sanity-check to your function:
var test = 0;
var running = running || false;
function go() {
if (running) {
// if an instance of go() is already running, the function quits
return false;
}
else {
running = true; // as the test variable survives I assume this will, too
test = test + 1;
setTimeout(go, 1000);
}
}
go();
As it's probable that test is going to be overwritten every time the page updates, I'd suggest ensuring that the assignation isn't going to overwrite a pre-existing count:
var test = test || 0;
var running = running || false;
function go() {
if (running) {
// if an instance of go() is already running, the function quits
return false;
}
else {
var running = true; // as the test variable survives I assume this will, too
test = test + 1;
setTimeout(go, 1000);
}
}
go();
Bear in mind that you could simply use the existence of the test variable to determine whether the function is currently running or not, but because I don't know if you'll be using that for other purposes I've chosen to create another variable for that purpose (which should hold either true or false Boolean values).

Change: go() to if(!test){ go() }
You'll also have to mend your test variable. So var test = test || 0;

Related

How to make part of a function only execute once until it's allowed to do otherwise

How can I call a javascript function (repeatedFunction()) repeatedly but make it so that, let's say an alert("This function is being executed for the first time"), is only activated the first time that repeatedFunction() is, but the //other code is always activated? And also, how can I make the alert() allowed to be activated for one more time, like if the repeatedFunction() was being executed for the first time again?
You can set a flag. Say for example, you have this following code:
var flagAlertExecd = false;
function repeatThis () {
if (!flagAlertExecd) {
alert("Only once...");
flagAlertExecd = true;
}
// Repeating code.
}
And to repeat this code, it is good to use setInterval.
setInterval(repeatThis, 1000);
Functions are objects. You can set (and later clear) a flag on the function if you like:
function repeatedFunction() {
if (!repeatedFunction.suppress) {
alert("This function is being executed for the first time");
repeatedFunction.suppress = true;
}
// ...other code here...
}
When you want to reset that, any code with access to repeatedFunction can clear the repeatedFunction.suppress flag:
repeatedFunction.suppress = false;
The flag doesn't have to be on the function, of course, you could use a separate variable.
That said, I would suggest looking at the larger picture and examining whether the alert in question should really be part of the function at all.
JavaScript closure approach will fit in this task. It has no global variables, and keeps your task in a single function.
var closureFunc = function(){
var numberOfCalls = 0;
return function(){
if(numberOfCalls===0)
{
console.log('first run');
}
numberOfCalls++;
console.log(numberOfCalls);
};
};
var a = closureFunc(); //0
a(); //1
a(); //2
var a = closureFunc(); //drop numberOfCalls to 0
a(); //1
http://jsfiddle.net/hmkuchhn/
You can do it by declaring a variable and incrementing it in your function. Using an if statement, you can check how many times it has been triggered. Code :
var count = 0;
function myfunc(){
if(count==0){
alert("Triggering for the first time");
count++;
}
//Your always triggering code here
}
Demo
This even tracks record of the how many times the function is triggered. It can be useful if you don't want to execute the alert() on nth time.
You can also use boolean values. Like this :
var firstTime = true;
function myfunc(){
if(firstTime){
alert("Triggering for the first time");
firstTime = false;
}
//Your always triggering code here
}
Demo
The second approach will not track the record of how many times the function has been triggered, it will just determine that whether the function is being invoked for the first time or not.
Both the approaches work fine for your purpose.
var firstTime = true;
var myFunction = function() {
if(firstTime) {
alert("This function is being executed for the first time");
firstTime=false;
}else{
//whatever you want to do...
}
}; //firstTime will be true for the first time, after then it will be false
var milliseconds = 1000;
setInterval(myFunction, milliseconds);
//the setInterval means that myFunction is repeated every 1000 milliseconds, ie 1 second.

SetInterval keeps setting when changing pages

So, I have a JavaScript issue that is probably as old as time, but I can't seem to figure it out. I have a form that takes up the whole page and has next and back buttons so the user can travel back and forth through the questions. (Single page app, no full refresh. If there was this would be easy!)
One of the requirements is to have a timeout function. So after they are idle after a cretin amount of time it logs them out to protect their information. The issue is that my interval keeps adding a new one every time I flip back and forth new pages. Thus creating multiple timers and insanity.
My code kind of looks like this.
var idle = 0;
var idleIntervalTimer = setInterval(timerIncrement, 1000); //This is what keeps being called
var counter = 0;
var timeout = 30;
var count = 20;
var resetCount = 20;
document.onmousemove = function() {
if(app.timer.get('available') === 'Yes'){ //I'm just using this to make sure that they have not already been logged out
count = resetCount;
idle = 0;
app.warning.close();
}
};
function timerIncrement() {
if(app.timer.get('available') === 'Yes'){
console.log(idle);
idle = idle + 1;
if (idle > 19 && count >= 0) {
count = count;
app.warning.show({ //This is just a warning message that shows up at the top of the page counting down before the app closes.
message: 'Logging out in <span class="warn">' + count + '</span> seconds.'
});
if(count != null || count >= 0){
count=count-1;
if (count === 0 && count != 'null'){
resetTimer();
app.workflow.resetWorkflow();
}
}
}
}
}
function resetTimer(){
count = resetCount;
idle = 0;
clearInterval(counter);
clearInterval(idleIntervalTimer);
app.warning.close();
}
I have tried a few different things. One being that I would set a blank variable at the top and use that blank variable to set the interval, but that didn't seem to work. I have also tried to detect if the interval was still active, but I don't really want to clear the interval, just not create another. Some help would be apprenticed very much!
I'm assuming that code gets called on every page flip. Don't set the interval timer immediately. You should create a function that will first clear it and then set.
For example do this instead:
var idleIntervalTimer;
function initIdleIntervalTimer(){
clearInterval(idleIntervalTimer);
idleIntervalTimer = setInterval(timerIncrement, 1000);
}
initIdleIntervalTimer();
Or try switching it the timer to the global scope, get rid of var idleIntervalTimer and do this:
clearInterval(window.idleIntervalTimer);
window.idleIntervalTimer = setInterval(timerIncrement, 1000);
It's a little ugly, but
window.clearInterval(localStorage['idleInterval'])
var idleIntervalTimer = setInterval(timerIncrement, 1000); //This is what keeps being called
window.localStorage['idleInterval'] = idleIntervalTimer;
EDIT: If you dont want to clear, wrap the entire init in a flag, eg
if (!window._intervalInitOccured){
window._intervalInitOccured = true;
//continue init

the counter is doubling

While working on my personal project, I've encountered a problem. The problem is every time my function loops the counter counts twice.
JavaScript Code:
function punch(){
var hit;
var h1=100;
h1-=1;
counter++;
hit=setInterval('punch()',2000);
}
What I wanted it to do is that every 2000 milliseconds the counter goes up 1.
In your original code every time the function punch is called is called again internally.
var counter = 0;
function punch(){
var h1=100;
h1-=1;
counter++;
}
var hit = setInterval(punch,2000);
window.setInterval(function(){
/// call your function here
}, 2000);
Call your function where commented and inside the function increment your counter.
var counter = 0;
var h1=100;
setInterval(punch,2000);
function punch(){
h1-=1;
counter++;
}
Here you go: http://jsfiddle.net/9JLdU/3/
<div id="counter"></div>
<script>
var hit;
var counter = 0;
window.punch = function()
{
var h1=100;
h1-=1;
counter++;
document.getElementById('counter').innerHTML=counter;
}
hit = setInterval('punch()',2000);
</script>
setInterval will cause the function to be called about every 2 seconds until cancelled. By including another call to setInterval within the function, another sequence of calls is established each time it is called, so eventually you'll have thousands of instances running, each incrementing the counter.
So either use one call to setInterval, or have the function call itself using setTimeout, which only runs once. Also, it's preferred to pass a function reference to setInterval and setTimeout as passing a string calls the Function constructor and is effectively a call to eval, which is needlessly expensive in terms of system resources.
var counter = 0;
function punch() {
// ...
counter++;
hit = setTimeout(punch, 2000);
}
punch();
or
var counter = 0;
function punch() {
// ...
counter++;
}
setInterval(punch, 2000);
The advantage of setTimeout is that you can easily vary the delay based on some other logic, or stop the sequence without cancelling the timeout.
Note that when doing:
hit = setInterval(...);
the value of hit is an index that can be used to cancel the interval, it is not the value returned by punch (which is undefined since there is no return statement).
The setInterval() method calls a function or evaluates an expression at specified intervals (in milliseconds).
The setInterval() method will continue calling the function until clearInterval() is called, or the window is closed.
Read about setInerval() Here
Syntax
setInterval(function,milliseconds)
Working Example here
<script>
var hit = 100;
counter = 0;
var myVar = setInterval(function() {punch()}, 1000);
function punch() {
hit--;
counter++;
}
</script>

setTimeout is not firing inside for loop

I have the following jquery code with setTimeout function to set a variable to false but it never works and the variable always remains to be true
for( var ff = 0; ; ff++)
{
if( dif == 0){
break;
}
if (locked){
// locked = false;
setTimeout( function(){ locked = false; },2000);
}
else{
LeftKeyPressed();
locked = true ;
setTimeout( function(){ locked = false; },3000);
dif--;
}
}
can anyone to help in how to set the locked variable to false after exactly two seconds from setting it to true.
Here's a fiddle of this issue.
Okey, since the requirements are what they are I dont know what exactly you want but this is closest I could manage to make: http://jsfiddle.net/db6gJ/
It calls method three times and gives you a change to do what you want to do when locked is false or true. Plus, it won't block the event loop (with that infinite for loop) so your site can make other tasks while timeOut call's are running.
javascript code also here:
var locked = true,
timesMax = 3,
timeCurrent = 0;
var inputLoop = function() {
var delay = 2000;
if(locked) {
// Do something when locked is true
console.log("locked is true!");
locked = false;
} else {
// Do something when locked is false
console.log("locked is false!");
locked = true;
delay = 3000;
}
timeCurrent++;
// call again after delay, but call only 3 times
if(timeCurrent < timesMax) {
setTimeout(inputLoop, delay);
}
};
// Launch it
inputLoop();
If you view your javascript console (in chrome: right mouse click -> inspect element -> console) it should print:
locked is true!
locked is false!
locked is true!
Also to be noted: your original code had alert('out'); when it's done, but to be honest, code will continue execution elsewhere while your "inputLoop" code is not doing anything else than waiting callback to be run and it's the way it should be.
If you wan't to know when it is called last time you could modify one of the previous lines to be:
// call again after delay, but call only 3 times
if(timeCurrent < timesMax) {
setTimeout(inputLoop, delay);
} else {
// Last call in this method
console.log('done!');
}

Why setInterval wont stop?

Why console.log(1) gets executed here forever:
var interval = setInterval(function() {
if (true) {
clearInterval(interval);
console.log(1);
}
}, 100);
It depends on the scope within which you're executing this code.
If interval is unique within its scope — be it global or function scope — then this will work as expected.
If, however, you execute this code within a loop (for example), then you are overwriting interval with some new interval on each iteration, breaking your clearInterval call for all but the very last setInterval call:
for (var i = 0; i < 3; i++) {
var interval = setInterval(function() {
if (true) {
clearInterval(interval);
console.log(1);
}
}, 100);
}
// ^ will give you one single console log entry,
// and two more console log entries per second forever
It's seems that your variable interval is used somewhere again. If I run code you provided it works as expected. I guess user Lightness has given a great explaination of this, also he provided piece of code where "closure problem" is obvious (which caused you problem too). I just want to add extra information. If you want your code inside of loop + setInteval works aparat you can do the following:
for (var i = 0; i < 3; i++) {
var o = {
i: i,
interval: null,
timer: function() {
if (true) {
clearInterval(this.interval);
console.log(this.i);
}
}
};
o.interval = setInterval(o.timer.bind(o), 1000);
}
DEMO
I hope it will be useful for someone.

Categories