Creating and Destroying Javascript Timeouts on the Fly

In Javascript, sometimes you just have to wait a few millisecond before you perform a task. A few examples

  • Assets need just a small window of time to render on screen
  • A button opens an overlay window and you want to close it after a set amount of time.
  • Delay an element animating in while you perform some other on page tasks.

All good things, all good things. Sometimes you may need to kill the delayed event after it was create but before it was performed. Let’s say you want a button to display something on screen and fade out after 5 seconds IF the user doesn’t close the element first.

var closeAThing = setTimeout(function() { console.log('remove thing automatically from screen'); }, 5000); $('.btn-close').click(function(evt) { evt.preventDefault(); console.log('remove the thing manually'); clearTimeout(closeAThing); });

Not to bad. But these variables are stored in a global scope and, every time you create one, you’re increasing the chance of a name collision unless you are careful with your variable conventions. So, to get around all this, here’s what I did. Maybe you’ll find it useful.

/* * ############################################### * Initialize Variables * ############################################### */ var pageTimeouts = {}; /* * ############################################### * Functions * ############################################### */ // set timeouts by name function createTimeout(name, func, time) { destroyTimeout(name); pageTimeouts[name] = setTimeout(func, time); } // destroy a timeout by name function destroyTimeout(name) { if (pageTimeouts.hasOwnProperty(name)) { clearTimeout(pageTimeouts[name]); } }

Why is this better? For one, it stores all timeouts in a single global object. That is kinda handy. It also cleans up creation, destruction, and checks if there is timeout of the same name and clears it before creating another. With this method, now you can create and destroy timeouts on the fly like so…

$('a.btn').on('click', function(evt) { evt.preventDefault(); $('.alert').addClass('animated bounceIn'); createTimeout('alert', function() { $('.alert').attr('class', ''); }, 5000); }); $('.alert a.close').on('click', function(evt) { evt.preventDefault(); $('.alert').attr('class', ''); destroyTimeout('alert'); });

I think it is pretty nifty. Hope it helps.