jQuery doTimeout: Like setTimeout, but better

| 5 | No TrackBacks

jQuery doTimeout takes the work out of delayed code execution, including interval and timeout management, polling loops and debouncing. In addition, it’s fully jQuery chainable!

Generally, setTimeout is used in JavaScript to delay the execution of some code, which is fairly easy to do and doesn’t require much, if any additional code. Where it starts to get a little more complicated is when you want to debounce or poll, or need any kind of timeout management—at which point keeping track of and clearing multiple timeout ids becomes critical and potentially messy. doTimeout maintains its own internal cache of ids and callbacks, so you don’t have to. Just think of setTimeout, but with additional management options, jQuery chainable, and with a simpler and more flexible API.

Basic setTimeout usage (see the basic examples):

// Like setTimeout.
$.doTimeout( 1000, function(){
  // do something in 1 second
});

// Like setTimeout, but easily cancelable (or forceable).
$.doTimeout( 'someid', 2000, function(){
  // do something in 2 seconds
});

// Override the preceding doTimeout with a new one.
$.doTimeout( 'someid', 1000, function( state ){
  alert( state ); // alert true in 1 second
}, true);

// Outright cancel the preceding doTimeout.
$.doTimeout( 'someid' );

// Or force the callback execution immediately (synchronously).
$.doTimeout( 'someid', false );

Create a polling loop (see the polling loop examples):

// Poll every 100ms until some_condition is true
$.doTimeout( 100, function(){
  if ( some_condition ) {
    // do something finally
    return false;
  }
  return true;
});

// Poll every 100ms until some_condition is true,
// cancelable (or forceable).
$.doTimeout( 'someid', 100, function(){
  if ( some_condition ) {
    // do something finally
    return false;
  }
  return true;
});

// Outright cancel the preceding doTimeout polling loop.
$.doTimeout( 'someid' );

// Or force the callback execution immediately
// (synchronously), canceling the polling loop.
$.doTimeout( 'someid', false );

// Or force the callback execution immediately
// (synchronously), NOT canceling the polling loop.
$.doTimeout( 'someid', true );

Debounce some event handlers (see the debouncing examples):

// Typing into a textfield (250ms delay)
$('input:text').keyup(function(){
  $(this).doTimeout( 'typing', 250, function(){
    // do something with text, like an ajax lookup
  });
});

// Window resize (IE and Safari fire this event continually)
$(window).resize(function(){
  $.doTimeout( 'resize', 250, function(){
    // do something computationally expensive
  });
});

And this is a jQuery plugin after all, so let’s chain with it (see the delay and polling loop examples):

var elems = $('a');

// Create a cancelable (or forceable) doTimeout.
elems
  .doTimeout( 'someid', 2000, function(){
    this.removeClass( 'remove-me-in-two-seconds' );
  })
  .addClass( 'remove-me-in-two-seconds' );

// Outright cancel the preceding doTimeout.
elems.doTimeout( 'someid' );

// Or force the callback execution immediately (synchronously).
elems.doTimeout( 'someid', true );

// "Poll" every 100ms, iterating over each element until
// none are left.
var idx = 0;
elems
  .doTimeout( 100, function(){
    var elem = this.eq( idx++ );
    if ( elem.length ) {
      elem.removeClass( 'remove-me-one-elem-at-a-time' );
      return true;
    }
  })
  .addClass( 'remove-me-one-elem-at-a-time' );

Just take a look at the documentation for methods, arguments and usage, as well as the examples, which include hover intent, delayed input on form fields, polling, and a few event handler debouncing demos (among others).

If you have any non-bug-related feedback or suggestions, please let me know below in the comments, and if you have any bug reports, please report them in the issues tracker, thanks!

No TrackBacks

TrackBack URL: http://benalman.com/mt/mt-tb.cgi/203

5 Comments

  • Very nice indeed!

  • niiice ben, i’ll be using this

  • Wow, very very useful, thankyou

  • A good timer, but I’m afraid I can’t get to work within a custom plugin - it seems the public cache of timeouts isn’t as public as I hoped within a custom plugin.

    I was setting the timeout with one function, then clearing it with another. I tried moving this to both private / both public functions, and then even nesting the cancelling function within the creating function (assuming that the timeout ID would be inherited by the cancelling function) - but no joy. I even tried assigning the Timeout to a public variable but that didnt work either.

    Still a good alternative for setInterval though!

  • I apologise, my mistake! As soon as I had given up with this, it suddenly came to me!!!

    I was doing it wrong! My cancelling function was called within the loop function - but as the loop function was always returning true, it could never stop.

    I just need to base the return boolean on my cancel scenario and it works fine!

    A great plugin!

Leave a comment

  • Markdown formatting is preferred, but you may use any of these HTML tags for style:
    a, b, i, br, p, strong, em, ul, ol, li, blockquote, pre, code.
  • Multi-line JavaScript code should be wrapped in <pre class="brush:js"></pre>
    (supported syntax highlighting brushes: js, css, php, plain, bash, ruby, html, xml)
  • Use &lt; instead of < and &gt; instead of > in the examples themselves.
  • Please preview your comment before submitting!