I've got a set of DOM elements, each of which needs its own timer. Eventually I'll be checking every X milliseconds to see whether a particular child of that element is present or not, but for right now it doesn't much matter what happens inside the timer.
The catch is that I want the timers to stop eventually. I can set up the timers with setInterval just fine, they work fine, but I can't figure out how to get clearInterval to end them.
I could probably do this with one big timer that watches every relevant element, but now I'm curious and want to figure this out. I figure I'm probably doing something wrong in the way I declare or start the timers, or clearInterval is targeting the setInterval functions incorrectly.
Here's my current code:
$(document).ready(function () {
let interval = 1000;
let base_count = 1;
let current_counts = [];
let timers = [];
// Count up from base to max and update the text to match.
function counter(p, maxCount, i) {
p.text(p.text().slice(0,5) + ': ' + current_counts[i]);
if (current_counts[i] > maxCount) {
clearInterval(timers[i]);
}
current_counts[i]++;
}
// Counters for each thing start at 1
current_counts = Array($('.thing').length).fill(base_count);
// Each thing gets its own timer.
timers = $('.thing').map(function (i, e) {
function start() {
return setInterval(
counter,
interval,
$(e),
10, // Max value for counter
i // Which paragraph are we on?
);
}
return start;
});
// Start the timers.
timers.each((i, e) => e());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p class="test1 thing">Test1</p>
<p class="test2 thing">Test2</p>
<p class="test3 thing">Test3</p>
As @pilchard said, MutationObserver should fit your use case. Though this does not answer your question so here its the answer:
On the browser setInterval returns an id for the interval created, so you can use it on clearInterval as below:
// create the interval
let intervalId = setInterval(callback, time);
// clear the interval using the id
clearInverval(intervalId);
e() returns all timers, then simple clear them out later
var tmrs = timers.map((i, e) => e());
// stop all timers
tmrs.forEach(x=> clearInverval(x)))
You aren't storing the intervals anywhere.
If you change the following:
timers.each((i, e) => e());
to:
timers = timers.map((i, e) => e());
it'll work.