Javascript: Clear All Timeouts

javascript: Clear all timeouts?

They are not in the window object, but they have ids, which (afaik) are consecutive integers.

So you may clear all timeouts like so:

var id = window.setTimeout(function() {}, 0);

while (id--) {
window.clearTimeout(id); // will do nothing if no timeout with id is present
}

how to clear all javascript Timeouts?

__EDIT__

To manage a collection of timeouts (and intervals), you could use following snippet.
This will allow to clear any timeouts or intervals set anywhere in code, although, you have to set this snippet before setting any timeout or interval. Basically, before processing any javascript code or external script which uses timeout/interval.

JS:

;(function () {
window.timeouts = {},
window.intervals = {},
window.osetTimeout = window.setTimeout,
window.osetInterval = window.setInterval,
window.oclearTimeout = window.clearTimeout,
window.oclearInterval = window.clearInterval,
window.setTimeout = function () {
var args = _parseArgs('timeouts', arguments),
timeout = window.osetTimeout.apply(this, args.args);
window.timeouts[args.ns].push(timeout);
return timeout;
},
window.setInterval = function () {
var args = _parseArgs('intervals', arguments),
interval = window.osetInterval.apply(this, args.args);
window.intervals[args.ns].push(interval);
return interval;
},
window.clearTimeout = function () {
_removeTimer('timeouts', arguments);
},
window.clearInterval = function () {
_removeTimer('intervals', arguments);
},
window.clearAllTimeout = function () {
_clearAllTimer('timeouts', arguments[0]);
},
window.clearAllInterval = function () {
_clearAllTimer('intervals', arguments[0]);
};

function _parseArgs(type, args) {
var ns = typeof args[0] === "function" ? "no_ns" : args[0];
if (ns !== "no_ns")[].splice.call(args, 0, 1);
if (!window[type][ns]) window[type][ns] = [];
return {
ns: ns,
args: args
};
}

function _removeTimer(type, args) {
var fnToCall = type === "timeouts" ? "oclearTimeout" : "oclearInterval",
timerId = args[0];
window[fnToCall].apply(this, args);
for (var k in window[type]) {
for (var i = 0, z = window[type][k].length; i < z; i++) {
if (window[type][k][i] === timerId) {
window[type][k].splice(i, 1);
if (!window[type][k].length) delete window[type][k];
return;
}
}
}
}

function _clearAllTimer(type, ns) {
var timersToClear = ns ? window[type][ns] : (function () {
var timers = [];
for (var k in window[type]) {
timers = timers.concat(window[type][k]);
}
return timers;
}());
for (var i = 0, z = timersToClear.length; i < z; i++) {
_removeTimer(type, [timersToClear[i]]);
}
}
}());

How to use it:

Set timeout(s)/interval(s) as usual:

var test1 = setTimeout(function(){/**/, 1000);
var test2 = setTimeout(function(){/**/, 1000);

Then you could use to clear both:

clearAllTimeout(); // clearAllInterval(); for intervals

This will clear both timeouts (test1 & test2)

You can use some namespaces to clear only specific timers, e.g:

// first (optional) parameter for setTimeout/setInterval is namespace
var test1 = setTimeout('myNamespace', function(){/**/, 1000); // 'myNamespace' is current namespace used for test1 timeout
var test2 = setTimeout(function(){/**/, 1000); // no namespace used for test2 timeout

Again, clearAllTimeout(); will clear both timeouts. To clear only namespaced one, you can use:

clearAllTimeout('myNamespace'); // clearAllInterval('myNamespace'); for namespaced intervals

This will clear only test1 timeout

You could for some reason wish to delete non namespaced timeouts only. You could then use:

clearAllTimeout('no_ns'); // clearAllInterval('no_ns'); for non namespaced intervals only

This will clear only test2 timeout in this example

See jsFiddle DEMO

__END of EDIT__

Old post specific to opening question here:

You could try that:

var timeouts = [];

timeouts.push(setTimeout(function() {
social2();
}, 5000));

timeouts.push(setTimeout(function() {
social1();
}, 5000));

//etc...

function clearAllTimeouts(){
for(var i = 0, z = timeouts.length; i < z; i++)
clearTimeout(timeouts[i]);

timeouts = [];
}

UPDATED following David Thomas comment

var timeouts = {'social' : [], 'antisocial' : []};

//a social timeout
timeouts.social.push(setTimeout(function() {
social1();
}, 5000));

//an anti-social timeout
timeouts.antisocial.push(setTimeout(function() {
antisocial1();
}, 5000));

function clearTimeouts(namespace){
for(var i = 0, z = timeouts[namespace].length; i < z; i++)
clearTimeout(timeouts[namespace][i]);

timeouts[namespace] = [];
}

//usage e.g
clearTimeouts("social");

How to stop all timeouts and intervals using javascript?

Updated answer after reading the duplicate I closed this question with -

It works and tested in Chrome on OSX

// run somethingvar id1 = setInterval(function() { console.log("interval", new Date())}, 1000);var id2 = setTimeout(function()  { console.log("timeout 1", new Date())}, 2000);var id3 = setTimeout(function()  { console.log("timeout 2", new Date())}, 5000); // not run          setTimeout(function()  { console.log("timeout 3", new Date())}, 6000); // not run
// this will kill all intervals and timeouts too in 3 seconds. // Change 3000 to anything larger than 10
var killId = setTimeout(function() { for (var i = killId; i > 0; i--) clearInterval(i)}, 3000);
console.log(id1, id2, id3, killId); // the IDs set by the function I used

How to clear all running timeouts before setting a new timeout

Even i had the same kind of problem. Try this

// Start listening on click.       
var timeoutHandle;
var active= false;
var $mic = $("#mic-container");
$mic.click(function(event){
//event.preventDefault();
if(active)
annyang.abort();
else
annyang.start({ autoRestart: false, continuous: false});

});

annyang.addCallback('start', function () {
active = true; console.log(active);
$mic.addClass('active pulse');
window.clearTimeout(timeoutHandle);
timeoutHandle = setTimeout(annyang.abort, 5000);

});

annyang.addCallback('end', function () {
window.clearTimeout(timeoutHandle);
timeoutHandle = setTimeout(function () {$mic.removeClass("active pulse result-match result-no-match");}, 200);
active=false; console.log(active);
});

annyang.addCallback('resultNoMatch', function () {
$mic.addClass("result-no-match");
$('.myErrorText').html('Try saying a valid command. See <a href="help.html" data-ajax="false">help</a> section for a list of valid commands!');
});

annyang.addCallback('resultMatch', function () {
$('.myErrorText').text('');
$mic.addClass("result-match");
});

How can I disable all setTimeout events?

When you call setTimeout(), store the timer ID so you can clear it. If you're creating many timeouts, then an array is a good option for storing the IDs. For example:

var timeouts = [];
//then, store when you create them
timeouts.push( setTimeout( { ... }, 1000) );

Then when you want to clear them:

for (var i = 0; i < timeouts.length; i++) {
clearTimeout(timeouts[i]);
}
//quick reset of the timer array you just cleared
timeouts = [];

As @Robert noted below, clearTimeout() won't throw an error if the timeout has already occurred, so there are no race/timing issues here.

React hooks - right way to clear timeouts and intervals

Defined return () => { /*code/* } function inside useEffect runs every time useEffect runs (except first render on component mount) and on component unmount (if you don't display component any more).

This is a working way to use and clear timeouts or intervals:

Sandbox example.

import { useState, useEffect } from "react";

const delay = 5;

export default function App() {
const [show, setShow] = useState(false);

useEffect(
() => {
let timer1 = setTimeout(() => setShow(true), delay * 1000);

// this will clear Timeout
// when component unmount like in willComponentUnmount
// and show will not change to true
return () => {
clearTimeout(timer1);
};
},
// useEffect will run only one time with empty []
// if you pass a value to array,
// like this - [data]
// than clearTimeout will run every time
// this value changes (useEffect re-run)
[]
);

return show ? (
<div>show is true, {delay}seconds passed</div>
) : (
<div>show is false, wait {delay}seconds</div>
);
}

If you need to clear timeouts or intervals in another component:

Sandbox example.

import { useState, useEffect, useRef } from "react";

const delay = 1;

export default function App() {
const [counter, setCounter] = useState(0);
const timer = useRef(null); // we can save timer in useRef and pass it to child

useEffect(() => {
// useRef value stored in .current property
timer.current = setInterval(() => setCounter((v) => v + 1), delay * 1000);

// clear on component unmount
return () => {
clearInterval(timer.current);
};
}, []);

return (
<div>
<div>Interval is working, counter is: {counter}</div>
<Child counter={counter} currentTimer={timer.current} />
</div>
);
}

function Child({ counter, currentTimer }) {
// this will clearInterval in parent component after counter gets to 5
useEffect(() => {
if (counter < 5) return;

clearInterval(currentTimer);
}, [counter, currentTimer]);

return null;
}

Article from Dan Abramov.

How do I clear all intervals?

You can find the "highest" timer identifier by creating a new timer that does "nothing" (by giving it an empty function to run, scheduled to run decades in the future), and then clear every timer between ids 1 and that identifier, like so:

// Get a reference to the last interval + 1
const interval_id = window.setInterval(function(){}, Number.MAX_SAFE_INTEGER);

// Clear any timeout/interval up to that id
for (let i = 1; i < interval_id; i++) {
window.clearInterval(i);
}

However, note that this is not guaranteed to work: the HTML standard does not actually prescribe how timeout/interval identifiers get allocated, so the assumption that we'll get a reference to the "last interval identifier + 1" is merely that: an assumption. It might be true for most browsers at the time of this answer, but there is no guarantee that's that will still be the case even in the next version of the same browser.

Clearing multiple timeouts in useEffect

I think with a minor tweak/refactor you can instead use an array of queued timeouts. Don't use the useEffect hook to manage the timeouts other than using a single mounting useEffect to return an unmounting cleanup function to clear out any remaining running timeouts when the component unmounts.

Use enqueue and dequeue functions to start a timeout and enqueue a stored payload and timer id, to be cleared by the dequeue function.

const [timerQueue, setTimerQueue] = useState([]);

useEffect(() => {
return () => timerQueue.forEach(({ timerId }) => clearTimeout(timerId));
}, []);

const enqueue = (id) => {
const timerId = setTimeout(dequeue, 3000, id);
setTimerQueue((queue) =>
queue.concat({
id,
timerId
})
);
};

const dequeue = (id) =>
setTimerQueue((queue) => queue.filter((el) => el.id !== id));

Demo

Edit clearing-multiple-timeouts-in-useeffect

setTimeout / clearTimeout problems

You need to declare timer outside the function. Otherwise, you get a brand new variable on each function invocation.

var timer;
function endAndStartTimer() {
window.clearTimeout(timer);
//var millisecBeforeRedirect = 10000;
timer = window.setTimeout(function(){alert('Hello!');},10000);
}

Resetting a setTimeout

You can store a reference to that timeout, and then call clearTimeout on that reference.

// in the example above, assign the result
var timeoutHandle = window.setTimeout(...);

// in your click function, call clearTimeout
window.clearTimeout(timeoutHandle);

// then call setTimeout again to reset the timer
timeoutHandle = window.setTimeout(...);


Related Topics



Leave a reply



Submit