Подтвердить что ты не робот

Может ли функция 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, чтобы при удалении элемента рабочая функция останавливалась.

Возможно ли подобное?

4b9b3361

Ответ 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();
    });
});