This question already has answers here:
How to terminate endless while loop via setTimeout in Javascript
(3 answers)
Closed 2 years ago.
The following code is work as the following
while loop>> bring a and b values>> settimeout>> check the value by if-condition>> continue it true, else break;
This code with settimeout and is not working:
var number = 0;
start_position: while (true) {
setTimeout(function() {
console.log("Anything you want to print");
var a = Math.random();
var b = Math.random();
}, 1000)
number++;
if (a > b) continue start_position;
break;
}
This code without settimeout and is work just fine:
var number = 0;
start_position: while (true) {
console.log("Anything you want to print");
var a = Math.random();
var b = Math.random();
number++;
if (a > b) continue start_position;
break;
}
This is another way I tried too:
var counter = 0;
var i = setInterval(function(){
var a=Math.random();
var b=Math.random();
console.log("a:",a);
console.log("b:",b);
counter++;
if(a<b || a=b) {
clearInterval(i);
}
}, 200);
Please, any suggestions?
Edit: This is more along the lines of what you want to accomplish. In your original case you had two problems A) The variables that you are checking are not in the correct function scopes and B) setTimeout functions get pushed into an event loop in javascript. Javascript will only run functions pushed into an event loop when the main thread is clear since javascript is single threaded. However because you have a while loop, that while loop will continue to run until it hits the break condition, never allowing your timeout function to be run, so it the while will run forever and the timeout function will never get run. This solution wraps the whole thing in a setInterval instead, setInterval will run periodically and then in this case is will clear itself when your condition is met.
var number = 0;
var interval;
function clear() {
if (interval !== undefined) {
clearInterval(interval);
}
callFunctionYouWantToMoveTo();
}
interval = setInterval(function() {
console.log("Anything you want to print");
a=Math.random();
b=Math.random();
number++;
if (a>b) return;
clear();
}, 1000)
Related
I have created the setTimeout which has a callback named run, Inside the run I have called a console.log(i) to print the value of I with i++ and once it reaches to 50, I want to clear the setTimeout with clearTimeout, I am calling setTimeout again with run making it recursive, but it doesn't work.
can somebody help me understand the concept better?
let i = 1;
var abc = setTimeout(function run(){
console.log(i);
if(i==50){
abc1();
}
i++;
setTimeout(run,100);
},100);
function abc1(){
clearTimeout(abc);
}
When you call setTimeout you get the ID of the timer returned. It's exactly what you've done here:
var abc = setTimeout(function run(){
However, that ID is valid only until the delayed function executes. Once it does, it's ineffective. When you call setTimeout(run,100); you will get a new ID for the timer. You need to capture that again, otherwise the ID gets lost and you have no way to stop it.
There is a final consideration - with your current code even if you were to correctly capture the ID calling abc = setTimeout(run, 100); that would still not stop the counter because it will attempt to stop the function that is running right now (which does nothing), instead of cancelling the execution of the next one:
let i = 1;
var abc = setTimeout(function run() {
console.log(i);
if (i == 50) {
abc1(); //this will clear the *current* timer
}
i++;
abc = setTimeout(run, 100); //this will set the *new* ID
}, 100);
function abc1() {
clearTimeout(abc);
}
In order to stop the execution you have two options. If you want to use your initial idea, you need to cancel the future execution after it is scheduled
let i = 1;
var abc = setTimeout(function run() {
console.log(i);
abc = setTimeout(run, 100); //this will set the *new* ID
if (i == 50) {
abc1(); //this will clear the *new* timer now
}
i++;
}, 100);
function abc1() {
clearTimeout(abc);
}
Alternatively, you can do it without using timer handles at all and just use the if condition to determine if you want to schedule another execution or not:
let i = 1;
setTimeout(function run() {
console.log(i);
if (i != 50) { //until 50 is reached
abc = setTimeout(run, 100); //schedule a new execution
}
i++;
}, 100);
The problem is the order of your operations.
if(i==50){
abc1();
}
If i reaches 50, the function abc1() will be called - which clears the interval.
i++;
setTimeout(run,100);
here you're restarting the interval.
You need to wrap it inside an else block.
let i = 1;
var abc = setTimeout(function run() {
console.log(i);
if (i == 50) {
abc1();
} else {
i++;
setTimeout(run, 100);
}
}, 100);
function abc1() {
clearTimeout(abc);
}
let i = 1;
var abc = setTimeout(function run(){
console.log(i);
if(i<50){
setTimeout(run,100);
}
i++;
},100);
You should run timeout only if timer not run out.
The setTimeout() inside run() in not assigned to any variable so it can't be cleared in any manner.
I suppose what you want is to overwrite abc so you must replace:
setTimeout(run,100);
by
abc = setTimeout(run,100);
Since var abc is only set once, at the first timeout, you are clearing only the very first Timeout, which very likely is already complete.
SetTimeout returns a numeric value, which is an ID to refer to that task. When you call clearTimeout, you must inform the ID of the timeout you want to clear, and now you are informing the ID for the very first timeout, which is already finished, thus can't be cleared.
If you wish to clear the last timeout, maybe you would like to always update abc with the IDs for each timeout, like this:
abc = setTimeout(run,100);
This is a weird way of doing a timed loop but you just need to clear (actually not in this case but I like to do it anyway as it is a good practice to release resources once you don't use them anymore) the timeouts (done by keeping track of abc handle) before creating new ones and return after clear on the given condition:
let i = 1;
let abc = setTimeout(
function run(){
console.log(i);
if(i==50){
abc1();
return;
}
abc1();
i++;
abc = setTimeout(run,100);
},
100
);
function abc1(){
clearTimeout(abc);
}
you need to add return after you call abc1 function. you clear timeout, but then code still running and call setTimeout(run,100) again.
let i = 1;
var abc = setTimeout(function run(){
console.log(i);
if(i==50){
abc1();
return;
}
i++;
setTimeout(run,100);
},100);
function abc1(){
clearTimeout(abc);
}
guys. It's a timer. I wanna run the timer and when it's end do something else(like a warning),and then run again with other amount of minutes. But I can't cause always only the second call is executed:
$(document).ready(function() {
timer(5,timer(25));
// timer(5);
// timer(25); do not work... only exec de last one
});
function timer(countTo,callback){
var time = 10; /* how long the timer runs for */
var initialOffset = '440';
var i = 1
var interval = setInterval(function() {
$('.circle_animation').css('stroke-dashoffset', initialOffset-(i*(initialOffset/countTo)));
$('h2').text(i);
if (i == countTo) {
clearInterval(interval);
}
i++;
}, 1000);
callback();
}
Which is the best solution? There is something that I am not understanding... Thanks anyway!
Well, first off:
timer(5,timer(25));
If you think this line will execute timer(5), and then at the end of timer(5) it will execute timer(25), you are mistaken. This is actually going to evaluate timer(25) immediately, and pass its return value (undefined) as the second parameter to timer(5,undefined).
If you intended to pass that as a callback, you need to pass a function. So you could do:
timer(5,timer.bind(null,25));
But, for that matter, you don't even check if callback exists before attempting to invoke it, so you probably are getting a reference error anyway.
timer(5,timer(25));
starts two timers and passes the result of the second (undefined) to the first as callback. You want:
timer(5,timer.bind(window,25));
And the callback needs to be executed if i==countTo ...
Is this what you want?
timer(5,function(){timer(25)});
Your problem is here:
timer(5,timer(25));
You should type
timer(5, function(){
timer(25)
});
//or using ES6 syntax
timer(5, () => timer(25));
because timer(25) returns its value (this function doesn't return value so it tries to invoke undefined), not that function.
Also read about closures, it might be helpful.
Instead of runing a callback(), you need to run the function itself (timer()). You'll also need to run a for loop inside your function that checks how many times the function has already run. If it reaches your desired maximum, break out of that. This way it won't run indefinitely.
In the following example, the timer() function executes five times, which is what I'm assuming you want by calling timer(5).
$(document).ready(function() {
timer(5);
});
function timer(countTo) {
for (var iterations = 0; iterations < countTo; iterations++) {
var time = 10; /* how long the timer runs for */
var initialOffset = '440';
var i = 1
var interval = setInterval(function() {
$('.circle_animation').css('stroke-dashoffset', initialOffset - (i * (initialOffset / countTo)));
$('h2').text(i);
if (i == countTo) {
clearInterval(interval);
}
}, 1000);
timer();
console.log("Iteration:", iterations + 1);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
To run the function 25 times after this, all you have to do is call timer(25) directly after timer(5):
$(document).ready(function() {
timer(5);
timer(25);
});
$(document).ready(function() {
timer(5);
timer(25);
});
function timer(countTo) {
for (var iterations = 0; iterations < countTo; iterations++) {
var time = 10; /* how long the timer runs for */
var initialOffset = '440';
var i = 1
var interval = setInterval(function() {
$('.circle_animation').css('stroke-dashoffset', initialOffset - (i * (initialOffset / countTo)));
$('h2').text(i);
if (i == countTo) {
clearInterval(interval);
}
}, 1000);
timer();
console.log("Iteration:", iterations + 1);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Hope this helps! :)
I'm trying to create fade in and fade out function with JavaScript, but it's not working. Please tell me what I'm doing wrong.I'm not getting transitioning effect.
var fade_in_btn = document.getElementById('fade-in'),
fade_out_btn = document.getElementById('fade-out'),
fading_div = document.getElementById('fading-div');
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
fade_out_btn.onclick = function(){
for (var i=100; i >= 0; i--) {
sleep(0010);
opacity_function(i);
}
}
fade_in_btn.onclick = function(){
for (var i=1; i <= 100; i++) {
sleep(0010);
opacity_function(i);
}
}
function opacity_function(opacity_value){
fading_div.style.opacity = opacity_value / 100;
fading_div.style.filter = 'alpha(opacity=' + opacity_value + ')';
console.log(fading_div.style.opacity);
}
Fiddle with HTML.
All code Working Fine. But from my point of view problem is the for...loop is not updating the value of opacity after each iteration; it's only updating the final value.
Please Help me to resolve this problem.
this is a pure JS answer that doesn't use requestAnimationFrame but i have chosen to discard your sleep function since it is an odd choice and bad practice (and yours doesn't work. also note that there can be no true sleep in JS.)
this works:
fade_out_btn.onclick = function(){
var i = 100;
var myint = setInterval(function(){
opacity_function(i);
i--;
if (i<0) clearInterval(myint);
console.log(i);
},10); //this is the number of ms between iterations of the codeblock in my setInterval function
}
[EDIT: some people were recommending setTimeout. I see no need for that, but in case you really want to use setTimeout, this is how I would do it:
var i = 100;
function fadeout(){
var myint = setTimeout(function(){
opacity_function(i);
i--;
if (i>0) fadeout();
},10);
}
fade_out_btn.onclick = fadeout;
notice two things:
1 - I pulled the definition of i outside of the function. you would have to be grabbing that value that you want to decrement from outside the function anyways, because your starting value for a fadeout would presumably not always be 100 but would be set to the current value of the opacity, i.e. the value of fading_div.style.opacity * 100.
2 - i bound a callback to the onclick.
regarding choosing between setInterval and setTimeout:
setInterval and setTimeout both simply schedule the execution of code. setInterval schedules events every x ms from when it is executed whereas a series of chained setTimeouts schedules an event in x ms, then executes again, then schedules another event in x ms. so there is a little bit of time overhead for setTimeout because the real time interval is x + (the time is takes to execute the codeblock once). it is possible have issues with using setInterval if the time it takes to execute once is larger than the specified interval but that would not affect such a simple program as yours. see here]
This question already has answers here:
All the setTimeouts inside javascript for loop happen at once
(2 answers)
Closed 10 years ago.
I searched around and found some others with similar issues, but I can't seem to find a solution or clear explanation.
var content = 'test<br />';
for( var i = 1; i < 6; i++ ) {
setTimeout(function() {
document.write(content);
}, 3000);
}
I'd like the code in the for loop to execute 5 times, with a three second delay between each loop. When it runs it, at least on the surface, looks like a three second delay at page load, then goes through all the loops with no delay.
What am I missing?
Your problem is that all the calls are happening after 3000 ms. Do perform each call 3s apart do this:
var content = 'test<br />';
for( var i = 1; i < 6; i++ ) {
setTimeout(function() {
document.write(content);
}, 3000 * i);
}
You probably need to use setInterval ('cause you're trying to run code at a certain "interval")
// first create an isolated namespace because we don't need to dirty the global ns //
(function(){
var counter = 0;
var maxIterations = 6;
var intervalReference = setInterval(function(){
// your code goes here //
alert('test');
// the stop condition //
++counter;
if (counter == maxIterations) {
clearInterval(intervalReference);
}
}, 3000);
}())
setInterval is probably the way to go (see Alin's answer) but if you were wanting to go down the setTimeout route, the code would look something like this:
var loop = 0;
var content = "test<br>";
function startTimeout(init){
if(init!==true){
document.write(content);
loop++;
}
if(loop<5){
setTimeout(startTimeout, 3000);
}
}
startTimeout(true);
I've been playing around with a site, in which I want to continue clicking a button for i amount of times every interval seconds.
My code is:
clickbidBtn1 = function() {
var bidBtn=document.getElementById("BidButton");
var interval = 15000;
for (var i=3; i>=0; i--){
setTimeout(bidBtn.click(1);,i*interval);
};
I've found out that GM executes all i amount of clicks at the same time, not with the intended delay. is there a way to delay the time of click? Say i wanted the function to click the button every 15 second for i amount of times.
I was thinking of giving it some more variables, and adding one variable in the settimeout code part, which only executes # the click, then comparing increased variables with current ones before going to the next settimeout... but haven't thought it through yet... it seems to be a complicated process for a simple process... :( i wll play around with it a bit
Use setInterval() for this.
One way:
var bidClickTimer = 0;
var numBidClicks = 0;
function clickbidBtn1 ()
{
var interval = 15000;
bidClickTimer = setInterval (function() {BidClick (); }, interval);
}
function BidClick ()
{
numBidClicks++;
if (numBidClicks > 3)
{
clearInterval (bidClickTimer);
bidClickTimer = "";
}
else
{
bidBtn.click (1);
}
}
clickbidBtn1 ();
Alternatively, without using global vars:
function clickbidBtn1 ()
{
var interval = 15000;
this.numBidClicks = 0;
this.bidClickTimer = 0;
this.BidClick = function () {
numBidClicks++;
if (numBidClicks > 3)
{
clearInterval (bidClickTimer);
bidClickTimer = "";
}
else
{
bidBtn.click (1);
}
};
this.bidClickTimer = setInterval (function(thisScope) {thisScope.BidClick (); }, interval, this);
}
clickbidBtn1 ();
Just to explain why your code does not work: You are calling the .click method immediately (putting () after a function name calls the function) and actually passing the return value of that function to setTimeout. The for loop is so fast that everything seem to happen at the same time.
You have to pass a function reference to setTimeout, e.g. an anonymous function:
setTimeout(function() {
bidBtn.click(1);
}, i*interval);