clearTimeout does not work in recursive function - javascript

I tried to use clearTimeout to escape from the recursive setTimeout function.
But it doesn´t work properly, so I just returned it using if function.
word.move = () => {
if (test >= 10) {
console.log(wodrd.move);
//clearTimeout(word.move);
return;
}
test++;
console.log(test);
word.node.style.top = `${test}px`;
setTimeout(word.move, speed);
};
How could it be stopped by using clearTimeout?

setTimeout returns a value that you need to save, in order to pass to clearTimeout later.
let wordMoveTimeout;
word.move = () => {
if (test >= 10) {
clearTimeout(wordMoveTimeout);
return;
}
// other logic here...
wordMoveTimeout = setTimeout(word.move, speed);
}
Read the documentation on how to use setTimeout here

Related

javascript setTimeout() is not working after few minutes and then it resolves without delay

I wrote a code for timer of 60 seconds but setTimeout() is executing properly for few minutes but after some time it is resolving the function but without delay and the function is getting resolved in each second.
Here, this.rateCardTimerText is init with zero in the first call.
Please provide any proper solution if available or is there any alternative way to achieve it then please also mention that.
onChangeTimerChangeInfinity() {
let no = Number(this.rateCardTimerText)
if (no >= 100) {
no = 0
this.getCurrencyList()
}
else {
no += 1.66
}
this.rateCardTimerText = no
this.forceUpdate()
setTimeout(this.onChangeTimerChangeInfinity.bind(this), 1000)
}
Use setInterval() instead.
setInterval( () => onChangeTimerChangeInfinity, 1000);
onChangeTimerChangeInfinity() {
let no = Number(this.rateCardTimerText);
if (no >= 100) {
no = 0;
this.getCurrencyList();
}
else {
no += 1.66;
}
this.rateCardTimerText = no;
this.forceUpdate();
}
Make sure you clear out the previous setTimeout each time you run it, like so:
let intervalObj;
onChangeTimerChangeInfinity() {
clearTimeout(intervalObj)
let no = Number(this.rateCardTimerText)
if (no >= 100) {
no = 0
this.getCurrencyList()
}
else {
no += 1.66
}
this.rateCardTimerText = no
this.forceUpdate()
intervalObj = setTimeout(this.onChangeTimerChangeInfinity.bind(this), 1000)
}
Also, just as with the above setInterval() option, you may end up with code tripping over itself because you're forcing this thing to fire every second regardless. If getCurrencyList() or forceUpdate() are async, consider rewriting a second function as a promise, then something like:
let intervalObj;
onChangeTimerChangeInfinity() {
clearTimeout(intervalObj)
doAsyncStuffInPromise().then( () => {
intervalObj = setTimeout(this.onChangeTimerChangeInfinity.bind(this), 1000)
})
}

How to stop nested timeOut with same names?

I am trying to use nested timeOut with the same names which is actually works like a loop, not exactly like it.
I try to use this example:
let i = 1;
setTimeout(function run() {
func(i);
setTimeout(run, 100);
}, 100);
from this link.
As you see in this link, I cant use interval and loop.
Here is my actual code:
let i = 0;
let x = setTimeout(async function run() {
if(i == 2) {
// I want to stop my x here completly
console.log(i)
clearTimeout(x);
}
try {
//some code here e.g:
console.log(10)
} catch (err) {
//some other code here e.g:
console.log(err)
}
i++;
x = setTimeout(run, 800);
}, 800);
And my output:
10
10
2
10
10
... //never stops
I also saw this link, but it is not my case.
Could any body please do something so that I can stop x completely?
Thanks in advance.
You need not the timeout reference, because if inside of the function the reference is invalid, because the timeout is called. Then you need to stop just to return.
let i = 0;
setTimeout(async function run() {
if (i == 2) {
console.log(i)
return
}
try {
//some code here e.g:
console.log(10)
} catch (err) {
//some other code here e.g:
console.log(err)
}
i++;
setTimeout(run, 800);
}, 800);
Because when you clearTimeout you don't stop it by return. So your timeout will set another timeout with x = setTimeout(run, 800);. All you need to do is return your clearTimeout(x) to stop your timeout function.
return clearTimeout(x);
In your code, I don't see any reason you need to clear timeout. Timeout run only once time. So if you execute it. It is done.

Cancel an infinite loop in JavaScript

I am trying to timeout a function in case it has an infinite loop. But the below does not work. Any idea why and how to fix it?
setTimeout(clearValues,1000);
function clearValues(){
i=0;
alert("hi "+i);
}
i=19
function infin(){
while(i>0){
console.log(i);
i++;
}
alert("Done");
}
infin();
In the below case, I get the alert displayed ( a bit later than expected ) and the console statements continue printing even after the alert. That means setTimeout did not wait for the loop to end in this case. Any explanation for this?
setTimeout(clearValues,500);
function clearValues(){
alert("clear");
}
function infin(){
for(i=0;i<10000;){
i=i+0.3;
console.log(i);
}
}
infin();
setTimeout works asynchronously, means it will run after 1000ms and the previous event loop is completed. Since the while loop will never be completed, the callback will never be called.
Add a condition to the loop if you want to exit it.
Another solution might be to use interval:
var code = function(){
console.log('tick');
};
var clock = setInterval(code, 200);
When you don't need it anymore:
clearInterval(clock);
It works, when you made the infin call with a slightly different change.
var i = 0;
setTimeout(clearValues, 1000);
var interval = setInterval(infin, 0);
function clearValues() {
out("clear");
clearInterval(interval);
}
function infin() {
if (i < 10000) { // if you be shure that you
i++;
out(i);
} else { // never reach the limit,
clearInterval(interval); // you can remove the four
} // commented lines
}
function out(s, pre) {
var descriptionNode = document.createElement('div');
if (pre) {
var preNode = document.createElement('pre');
preNode.innerHTML = s + '<br>';
descriptionNode.appendChild(preNode);
} else {
descriptionNode.innerHTML = s + '<br>';
}
document.getElementById('out').appendChild(descriptionNode);
}
<div id="out"></div>

Confused with set timeout

I'm really confused how these work...the timeout does not seem to keep running it calls begin_anim once and then thats it....
So am hoping someone can see where i went wrong and explain how I implement this?
This is my code:
//test data:
//type = 'up';
//div = document.getElementById('theid');
//marginL = -400;
function timeout_begin(type,div,marginL){
setTimeout(begin_anim(type,div,marginL),1000);
}
function begin_anim(type,div,marginL){
if(type == 'up'){
if(marginL >= '-200'){
if(marginL > '-200'){
div.style.marginLeft = '-200px';
}
return false;
}
marginL += 2;
div.style.marginLeft = marginL+'px';
}
return false;
}
Hope you can help!
You're looking for setInterval!
Also, it's probably better to pass an actual function in, and you can hold a reference to the loop so you can stop it running later if you want to:
var animationLoop = setInterval(function () {
begin_anim(type, div, marginL);
}, 1000);
clearInterval(animationLoop); // This would then stop the loop.
First, you want setInterval, not setTimeout
Second, you'll pass a reference to a function, not a call to a function. Something like:
function timeout_begin(type,div,marginL)
{
setTimeout(
function() {
begin_anim(type,div,marginL);
},
1000
);
}
setTimeout is supposed to call the function only once.
if you want to call the method repeatedly use setInterval(function(){}, 1000/*duration*/)
setTimeout is only expected to execute the function once after the given timeout. See the documentation here: http://www.w3schools.com/jsref/met_win_settimeout.asp
You're probably looking for setInterval (http://www.w3schools.com/jsref/met_win_setinterval.asp) which executes the code at the interval you set until clearInterval is called.

Queueing setTimeout in javascript

I need to flash an element off and on. This works but I don't really like the code. Is there a nice way of doing this?
setTimeout(function(){
toggle();
setTimeout(function(){
toggle();
setTimeout(function(){
toggle();
setTimeout(function(){
toggle();
}, 100);
}, 100);
}, 100);
}, 100);
I'm using jQuery too if that helps.
function toggle_multiple(n)
{
var toggled = 0;
function toggle_one_time()
{
toggle();
toggled += 1;
if (toggled <= n)
setTimeout(toggle_one_time, 100);
}
toggle_one_time();
}
And just call toggle_multiple(4).
A recursive approach:
function multiTimeoutCall (callback, delay, times) {
if (times > 0){
setTimeout(function () {
callback();
multiTimeoutCall (callback, delay, times - 1);
}, delay);
}
}
Usage:
multiTimeoutCall (toggle, 100, 4);
Edit: Yet another approach, without filling the call stack:
function multiTimeoutCall (callback, delay, times) {
setTimeout(function action() { // a named function expression
callback();
if (--times > 0) {
setTimeout (action, delay); // start a new timer
}
}, delay);
}
I could used arguments.callee instead of a named function expression, but seems that it will be deprecated some day in ECMAScript 5...
Why not use setInterval?
var toggler = function() {
if (++self.counter >= self.BLINK_AMOUNT * 2) {
self.counter = 0;
window.clearInterval(self.timer);
return;
}
toggle();
};
toggler.BLINK_AMOUNT = 1;
toggler.counter = 0;
toggler.timer = window.setInterval(toggler, 100);
I can't remember whether or not IE properly implements the self variable in a timer callback - if it doesn't, use a uniquely named global variable instead.
I would use a blinking effect. For jquery there's pulsate, hope that works for you.
Here's yet another version for simplicity:
for (var i= 0; i<4; i++)
setTimeout(toggle, (i+1)*100);
For larger numbers an interval may be more appropriate, but if it's just four toggles multiple timeouts are fine.
Generalizing 'unknown's' idea of using setInterval,
function schedule(fn, max, delay)
{
var counter = 0;
var interval = setInterval(
function()
{
if(counter++ === max)
clearInterval(interval);
fn();
}
, delay);
}
Usage:
schedule(toggle, 4, 100);
If its just flashing that is required, why not use the jQuery animate ? I use the following to direct user attention to messages. But you can do this for any element -
$("#message_box").fadeOut(450).fadeIn(350);
If you want it multiple times, do this -
$("#message_box").fadeOut(450).fadeIn(350).fadeOut(450).fadeIn(350);
You can do like this:
function toggleMany(cnt) {
toggle();
if (--cnt >= 0) window.setTimeout('toggleMany('+cnt+')', 100);
}
toggleMany(4);

Categories