how to clear all javascript Timeouts?

Mohammad Masoudian picture Mohammad Masoudian · Jun 12, 2013 · Viewed 8.2k times · Source

i have a loop function that in first 5 seconds it runs social1() and in second 5 seconds it runs social2() then loop ...

i have 2 hover functions too

i need clear all active timeouts because when i hover on images (.social1 & .social2), i can see that multiple timeouts are running

how to fix this?

function social1() {
    $('.social1').fadeTo(500, 1);
    $('.social2').fadeTo(500, 0.5);
    timeout = setTimeout(function() {
          social2();
    }, 5000);
}
function social2() {
    $('.social1').fadeTo(500, 0.5);
    $('.social2').fadeTo(500, 1);
    timeout = setTimeout(function() {
          social1();
    }, 5000);
} 


$(document).ready(function ()
{
    social1();

    $('.social1').hover(
        function () {
            window.clearTimeout(timeout);
            social1();
        },
        function () {
            timeout = setTimeout(function() {
                  social2();
            }, 5000);
        }
    );
    $('.social2').hover(
        function () {
            window.clearTimeout(timeout);
            social2();
        },
        function () {
            timeout = setTimeout(function() {
                  social1();
            }, 5000);
        }
    );

Answer

A. Wolff picture A. Wolff · Jun 12, 2013

__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");