setTimeout is not firing inside for loop - javascript

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!');
}

Related

setTimeout being called multiple times

I can't figure out why setTimeout is being called multiple times in my code.
Here's a snippet of the code with what I thought was irrelevant removed:
let dead;
setup()
{
dead = false;
}
draw()
{
if(fell == true)
{
dead = true;
}
mechanics();
}
function mechanics()
{
let triggerVar;
if(dead == true)
{
triggerVar = 1;
dead = false;
}
if(triggerVar == 1)
{
setTimeout(resetG, 1500);
triggerVar = 0;
}
}
function resetG()
{
lives -= 1;
position = 0;
}
I can't tell what I'm doing wrong because whenever the character dies and setTimeout is called, it is actually not only called after the delay but also for the exact same duration after it is triggered. So in this case it is triggered first after 1500 millis and then every frame for another 1500 millis.
I managed to find the problem, which was not with the code I posted. The problem was that the constructor code that makes the object that changes dead to true if certain conditions are met was being called every frame from the moment it triggered death until the first instance of setTimeout kicked in, which means setTimeout was called every frame for 1500 milliseconds.
Chances are that you mechanics() function is called multiple times, you may give a variable to the settimeout like:
let timeoutID= setTimeout(resetG, 1500);
And in the proper place to clear it, for example after lifecycle
clearTimeout(timeoutID);

Exit the loop abruptly

Let's imagine the following code:
function DoSomethingHard(parameter1, parameter2, parameter3){
// Do Something Hard Here
}
var i;
for(i = 0; i <= stuff.length; i++) {
// "stuff" is an array
DoSomethingHard(stuff[i].something1, stuff[i].something2, stuff[i].something3);
}
$( "#button_to_cancel" ).click(function() {
//something to cancel
});
Suppose the array "stuff" has 100 positions, so the for loop will run
100 times, ie, it will do "Do Something Hard" 100 times.
Let's also consider that "DoSomethingHard" takes about 5 seconds to run
completely.
My question is: How do I manage the cancellation of "DoSomethingHard"? For example, if it has already run 50 times, how can I cancel the subsequent executions through a button? I did not succeed in my attempts and it always ends up running the whole loop ....
Thanks in advance :)
Javascript is single threaded, and a for loop executes until it is finished. I would do something like this to allow time for the cancel.
function DoSomethingHard(param){
//do something
}
var i = 0;
var loopInterval = setInterval(function() {
if (i >= stuff.length) {
clearInterval(loopInterval);
return;
}
DoSomethingHard(stuff[i]);
i++
}, 10);
$( "#button_to_cancel" ).click(function() {
clearInterval(loopInterval);
});
You can make use of setInterval to call the function and when you have a click event you can clear the intervals
var mytimeout;
var i;
for(i = 0; i <= stuff.length; i++) {
// "stuff" is an array
mytimeout = window.setInterval(DoSomethingHard(stuff[i].something1, stuff[i].something2, stuff[i].something3), 2000);
}
$( "#button_to_cancel" ).click(function() {
//something to cancel
window.clearInterval(mytimeout)
});
Simplest way as I see it:
function DoSomethingHard(parameter1, parameter2, parameter3){
//Do Something Hard Here
}
var i;
var active = true; //as of now, we want to process stuff
for(i=0;i<=stuff.length;i++){
//"stuff" is an array
if(active){
DoSomethingHard(stuff[i].something1, stuff[i].something2, stuff[i].something3);
}else {
active = true; //reset active in case we want to run loop again later on
break; // break out of loop
}
}
$( "#button_to_cancel" ).click(function() {
active = false;
});
You can't easily cancel it with a click on a button, unless you use recursion or iterators instead of a loop.
But you can cancel the loop inside itsself with a break; statement when some condition is met. For example you could write:
var result;
for(i=0;i<=stuff.length;i++){
result = DoSomethingHard(stuff[i].something1, stuff[i].something2, stuff[i].something3);
if (result === 'error' || i === 50) break;
}
This will end the loop if result becomes the 'error' (or anything else your return from inside the function) or when i reaches 50.
Now that i think of it, it's possible with a button click, but it requires more code and is inefficient. give me a minute.
Update: I would not advice this ppttern either, but it's pretty flexible:
var exitCondition,
doSomethingHard = function doSomethingHard(parameter1, parameter2, parameter3){
// Do Something Hard Here
},
i,
length = stuff.length,
result;
for (i = 0; i <= length; i++) {
// "stuff" is an array
result = doSomethingHard(stuff[i].something1, stuff[i].something2, stuff[i].something3);
if (exitCondition( result, i )) break;
}
$( "#button1_to_add" ).click(function() {
exitCondition = function( result, index ) {
return index === 50;
});
});
$( "#button2_to_cancel" ).click(function() {
exitCondition = null;
});
The clue here is to have an exit condition (or multiple) that you check inside the loop and have the button update this condition.
You can not stop a for loop from UI interaction because everything is running in a single thread and your action will execute only after loop executes completely. You can use setInterval as #jason p said.
I solve this way:
function DoSomethingHard(parameter1, parameter2, parameter3){
//Do Something Hard
var timer = window.setInterval(function(){
var page = $$('.page').data('page');
console.log("The page is: "+page);
if(page != 'preview'){
//Cancel...
console.log('Aborted');
clearInterval(timer);
}
},1000);
}
That is, i changed the scope. Instead using button click, i monitered when user leave the page, so cancel it.
You need to note that loop is synchronous where as your function isn't. Loop won't wait for DoSomethingHard() to compleye before the next iteration begins.In just a few milliseconds DoSomethingHard has been called over a hundred times! and your loop gets over so in essence break is of no use here.I think no language construct can help here
So what to do?
You need to decide whether to do something or not in the function itself create a global flag and check it inside the function
function DoSomethingHard(){
if(flag50done){
return;
}else{
//do what this fn was meant for
}
}
You can change value of flag50done with a click of a button and further actions would get stopped due to the return
In case DoSomethingHard is some 3rd party function which you cannot modify you can wrap it in another function say runDecider
function runDecider(a,b,c){
//add flag check here
if(flag50done){
return;
}else{
DoSomethingHard(a, b, c);
}
}
and call this in the loop
var result;
for(i=0;i<=stuff.length;i++){
result = runDecider(stuff[i].something1, stuff[i].something2, stuff[i].something3);
}

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.

Function to exit a parent function

I have a loop that runs indefinitely until I tell it to stop. I am actually using requestAnimationFrame and a lot more is going on, but the below example is just to simplify my question.
var _stop = false;
var loop = function () {
while (!_stop) {
if (some condition is met) {
stop();
}
/* Do something. */
loop();
}
};
function stop() {
_stop = true;
}
Now this all works great, but it will still run /* Do something */ one more time before it actually stops. I want it to stop immediately and return.
Of course this can be done like so:
if (some condition is met) {
stop();
return;
}
But is there a way to include the return part into stop();? This doesn't do what I want for obvious reasons:
function stop() {
_stop = true;
return;
}
But is there a way to achieve this?
var _stop = false;
try {
var loop = function () {
if(!_stop) {
if (some condition is met) {
stop();
}
/* Do something. */
loop();
}
};
} catch(e) {
}
function stop() {
_stop = true;
throw new Error("USE IT WITH PRECAUTION");
}
The loop above does you job of exiting entire loop, But I will say its horribly wrong way of doing thing as ideally function should be
1) mutating the state variables
2) or should be computing the values.
3) or should be determining error state to stop the execution further
It should never be bothered about how the control flow of function caller is and ways to stop function caller execution flow.
It sounds like you want to check the condition (before) every time the work is done. To do this with a _stop variable (as opposed to simply checking the condition in the while condition itself), you have to:
Set the variable based on the condition before starting the loop
Do your work
Set the variable based on the condition before the next loop iteration
Whether you accomplish this with a while() loop or a do while() loop, the process will be the same. Adding a pre-loop check to your example will prevent the work from being done if the user has already exited:
var _stop = false;
// Call loop() when required
var loop = function () {
// Check condition before first iteration
if (/* some condition is met */) {
stop();
}
while (!_stop) {
/* Do your work */
// Check condition before every subsequent iteration
if (/* some condition is met */) {
stop();
}
loop();
}
};
function stop() {
_stop = true;
}
Is there a reason you are recursively calling loop() instead of calling it once and doing all of your work within the contained loop until the user exits? This more simplified version might work for you:
var _stop = false; // Set it initially, could also use checkStopRequired() here
// Call loop() when required
var loop = function () {
// Check condition before first iteration
_stop = checkStopRequired();
while (!_stop) {
// Do your work, setting _stop to true if work returns early
_stop = !doMyWork();
// Check condition before every subsequent iteration
_stop = checkStopRequired();
}
};
function checkStopRequired() {
// Return true if should stop, false if should continue
}
When doing the work required for each loop iteration, you may want to check the exit condition before any expensive operations to allow the whole thing to halt as soon as an exit condition is met, as opposed to waiting for the work to finish. This obviously depends on what work you're doing and what the exit conditions are.
An example of the function to be called within the loop, which will help you set _stop if the stop condition is met part-way through:
function doMyWork() {
// Get user input here...
if (checkStopRequired()) { return false; }
// Get data here...
if (checkStopRequired()) { return false; }
// Do logic here...
if (checkStopRequired()) { return false; }
// Render objects here...
// Return successful result
return true;
}
it might not be the optimal way to do this, but this can be done like this:
var _stop = false;
var flag=0;
var loop = function () {
if(!_stop) {
if(flag){
return;
}
if (some condition is met) {
stop();
_stop = true;
loop();
}
/* Do something. */
loop();
}
};
function stop() {
//_stop = true;
toReturn();
}
function toReturn(){
flag=1;
}

javascript loop going mental

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;

Categories