Может ли функция setInterval останавливаться?
У меня есть jsFiddle с примером для работы.
$().ready(function() {
$('.test').each(function() {
$this = $(this);
$this.data('Worker', function() {
$('#stop').html((parseInt($('#stop').html()) + 1))
})
setInterval($this.data('Worker'), 100);
});
$('#stop').click(function() {
// I want the worker function to stop being triggered here
$('.test').remove();
});
});
То, что я хотел бы сделать, - это привязать рабочую функцию к элементу в DOM, чтобы при удалении элемента рабочая функция останавливалась.
Возможно ли подобное?
Ответы
Ответ 1
Здесь вы идете:
var stopBtn = $( '#stop' );
$( '.test' ).each(function ( i, elem ) {
var tid = setInterval(function () {
if ( elem.parentNode ) {
stopBtn.html(function ( i, num ) { return parseInt(num,10) + 1; });
} else {
clearInterval( tid );
}
}, 1000);
});
stopBtn.click(function () {
$( '.test' ).remove();
});
Объяснение:
Прежде всего нам нужно закрыть - функция интервалов должна знать, какой тест-DIV является ее "владельцем", ergo, нам нужно передать ссылку на DIV в функцию интервала. В моем коде эта ссылка хранится в переменной elem
, которая доступна внутри функции интервалов из-за закрытия. Таким образом, функция интервала проверяет, не прикреплен ли ее DIV-владелец к DOM (путем изучения его родительского элемента node). Если это так, кнопка остановки увеличивается. Если это не так, интервал очищается. Однако, чтобы очистить интервал, мы требуем его идентификатор таймера. У нас есть этот идентификатор, потому что мы сохранили его внутри переменной "tid" (вызов setInterval возвращает идентификатор таймера).
Live demo: http://jsfiddle.net/simevidas/ZjY7k/15/
Ответ 2
Поздно к партии, но я решил так:
var id = setInterval(function()
{
if(some_condition)
{
clearInterval(id);
}
}, 1000);
Определенно самый простой выход из всего: отсутствие ненужного хранения, никаких трюков.
Ответ 3
Другой способ, которым вы можете удалить интервалы, - использовать clearInterval внутри интервала.
window.setInterval(function(){
// Do all your stuff here
if(/*something something*/){
window.clearInterval(this);
alert("The interval didn't clear");
}
}, /*However long*/);
Если интервал не ясен, он покажет предупреждение: "Интервал не очистился". В противном случае интервал успешно очищается.
Ответ 4
Это малоизвестный факт, но setInterval
возвращает значение, которое можно использовать с clearInterval
для отмены интервала.
var result = setInterval(function, delay);
// at some point later...
clearInterval(result);
Ответ 5
Я подозреваю, что правильный способ реализации "самоограничивающего" интервала - реализовать интервал через серию тайм-аутов.
В полу-псевдокоде:
setTimeout(function repeat() {
if (continue_to_run) // this code here may cause timing to be inaccurate
setTimeout(repeat, interval_duration);
do_task_on_interval();
}, 0)
Этот повторяющийся таймер очищается после себя.
Ответ 6
Использовать clearInterval:
$().ready(function () {
$('.test').each(function () {
$this = $(this);
$this.data('Worker', function () { $('#stop').html((parseInt($('#stop').html()) + 1)) })
$this.data('intervalId', setInterval($this.data('Worker'), 100));
});
$('#stop').click(function () {
$('.test').each(function() { clearInterval($(this).data('intervalId')); }).remove();
});
});