<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>unscriptable.com &#187; Event Handling</title>
	<atom:link href="http://unscriptable.com/category/events/feed/" rel="self" type="application/rss+xml" />
	<link>http://unscriptable.com</link>
	<description>Just another WordPress site</description>
	<lastBuildDate>Mon, 26 Mar 2012 01:47:11 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Debouncing Javascript Methods</title>
		<link>http://unscriptable.com/2009/03/20/debouncing-javascript-methods/</link>
		<comments>http://unscriptable.com/2009/03/20/debouncing-javascript-methods/#comments</comments>
		<pubDate>Fri, 20 Mar 2009 07:21:21 +0000</pubDate>
		<dc:creator>John Hann</dc:creator>
				<category><![CDATA[dojo]]></category>
		<category><![CDATA[Event Handling]]></category>
		<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://unscriptable.com/?p=7</guid>
		<description><![CDATA[... a user could simply lean on the Tab key to navigate from one end of the form to the other.  If the user were lucky enough to be on a fast network connection and had a fast enough browser, this would go fairly smoothly.  However, the server would get absolutely hammered by all of the XHR requests necessary to populate the side-bar!  ]]></description>
			<content:encoded><![CDATA[<p>Back in 2006, I was the lead front-end architect for a mission-critical Web 2.0 application.  Yah-yah, aren&#8217;t they all mission-critical?  Yes, but this one really was critical since it was one of those make-or-break moments for the product.  What made this project really interesting were the unrealistic expectations the product managers had of web apps.  </p>
<p>Sometimes, pressure like this can lead to creativity and innovation.  On this occasion, it helped me reach back in to my electrical engineering coursework to apply a hardware concept to software programming.<br />
<span id="more-698"></span><br />
Just imagine this:</p>
<ol>
<li>You are tasked to write the entire Javascript-based framework from scratch, including the core functions (inheritance, declarations, event connections), DOM manipulation and querying, a widget framework, MVC, drag-and-drop, and dozens of custom widgets to boot.</li>
<li>You are given unintuitive and un-web-like requirements to ensure that the app allowed customers to adhere to strict FDA regulations.</li>
<li>The product managers had no experience with web app development so they designed the requirements for a Windows application.  You know: modal dialogs, instant retrieval of large amounts of data (as if it were coming straight from the disk), workflows that depended on sequenced calls to/from the back-end systems, etc.</li>
</ol>
<p>Oh, and did I mention there was a deadline and only two of us were hired to code the entire UI side of the project?  </p>
<p>Well, I am always up for a challenge, especially if somebody says, &#8220;It can&#8217;t be done&#8221;.  So needless to say, I had to really use my brain on this project.  </p>
<p>One of the more interesting requirements was to show the user a summary side-bar of information pertaining to the current field (i.e. the input element that had focus).  This side-bar information could be from several kilobytes to more than 100 kB.  The data had to be fetched via XHR from the back-end and displayed each time the user entered a new field.  </p>
<p>This presented a major problem if the user was keyboard-oriented and preferred to use the Tab key to move from field to field.  There could be hundreds of fields on the screen, and a user could simply lean on the Tab key to navigate from one end of the form to the other.  If the user were lucky enough to be on a fast network connection and had a fast enough browser, this would go fairly smoothly.  However, the server would get absolutely hammered by all of the XHR requests necessary to populate the side-bar!  </p>
<p>Luckily, I had handled this situation several times before.  A simple setTimeout and a few state variables fixes this problem fairly easily.  But there were several of these situations in this project, and I wanted to build something reusable.  </p>
<p>The more I thought about it, the more it felt like <a href="http://en.wikipedia.org/wiki/Switch#Contact_bounce">contact debouncing</a>.  Debouncing means to coalesce several temporally close signals into one signal.  For example, your computer keyboard does this.  Every time you hit a key, the contacts actually bounce a few times, causing several signals to be sent to the circuitry.  The circuitry determines that the bouncing has ended when no bounces are detected within a certain period (the &#8220;detection period&#8221;).  Since people can&#8217;t really type faster than roughly 10 keys per second, any signals happening within 100 msec of each other, for example, are likely part of the same key press.  (In practice, you should at least halve this, so about 50 msec for our keyboard example.  I have no idea what keyboards really use, by the way.  This is just an illustration.)</p>
<h2>Debouncing != Throttling</h2>
<p>Whenever I bring up the concept of debouncing, developers try to cast it as just a means of throttling.  But that&#8217;s not true at all.  Throttling is the reduction in rate of a repeating event.  Throttling is good for reducing mousemove events to a lesser, manageable rate, for instance.</p>
<p>Debouncing is quite more precise.  Debouncing ensures that exactly one signal is sent for an event that may be happening several times &mdash; or even several hundreds of times over an extended period.  As long as the events are occurring fast enough to happen at least once in every detection period, the signal will not be sent!  </p>
<p>Let&#8217;s relate this back to our keyboard-oriented user and our huge set of form fields.  Throttling here would certainly help.  We could reduce the number of XHR requests to a lower rate than the computer&#8217;s key repeat rate for sure!  However, we&#8217;d still be fetching from the back-end more times than necessary, and the occasional re-rendering of the fetched data could temporarily freeze up the browser, deteriorating the user experience.  </p>
<p>Debouncing on the other hand could better detect when the user stopped leaning on the keyboard and had arrived at their destination.  It&#8217;s certainly not perfect.  The user still may overshoot their destination, hesitate, and back-track, causing enough delay for the debounce detection period to expire.  However, our tests showed that debouncing did a much better job of reducing XHR requests than throttling.  </p>
<h2>Implementation</h2>
<p>The original debounce method was rather large and clunky.  I consider it a prototype.  A proof of concept.  I ended up needing debouncing a few times since that project and rewrote it each time, trying to improve it.  I&#8217;ve finally devised something that feels good enough to share.  </p>
<p>The latest rendition takes two parameters: the detection period (&#8220;threshold&#8221;) and a Boolean indicating whether the signal should happen at the beginning of the detection period (true) or the end (&#8220;execAsap&#8221;).</p>
<p>Here it is:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">Function</span>.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">debounce</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>threshold<span style="color: #339933;">,</span> execAsap<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> func <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">// reference to original function</span>
        timeout<span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// handle to setTimeout async task (detection period)</span>
    <span style="color: #006600; font-style: italic;">// return the new debounced function which executes the original function only once</span>
    <span style="color: #006600; font-style: italic;">// until the detection period expires</span>
    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">function</span> debounced <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> obj <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">// reference to original context object</span>
            args <span style="color: #339933;">=</span> arguments<span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// arguments at execution time</span>
        <span style="color: #006600; font-style: italic;">// this is the detection function. it will be executed if/when the threshold expires</span>
        <span style="color: #003366; font-weight: bold;">function</span> delayed <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #006600; font-style: italic;">// if we're executing at the end of the detection period</span>
            <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>execAsap<span style="color: #009900;">&#41;</span>
                func.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span>obj<span style="color: #339933;">,</span> args<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// execute now</span>
            <span style="color: #006600; font-style: italic;">// clear timeout handle</span>
            timeout <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">;</span> 
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
        <span style="color: #006600; font-style: italic;">// stop any current detection period</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>timeout<span style="color: #009900;">&#41;</span>
            clearTimeout<span style="color: #009900;">&#40;</span>timeout<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #006600; font-style: italic;">// otherwise, if we're not already waiting and we're executing at the beginning of the detection period</span>
        <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>execAsap<span style="color: #009900;">&#41;</span>
            func.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span>obj<span style="color: #339933;">,</span> args<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// execute now</span>
        <span style="color: #006600; font-style: italic;">// reset the detection period</span>
        timeout <span style="color: #339933;">=</span> setTimeout<span style="color: #009900;">&#40;</span>delayed<span style="color: #339933;">,</span> threshold <span style="color: #339933;">||</span> <span style="color: #CC0000;">100</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>It works by issuing a setTimeout at the specified detection period.  Each time the function is called, the setTimeout is canceled and issued again.  This serves as our detection mechanism, but using reverse logic.  If/when the setTimeout executes, we know that our function was not called within the detection period.</p>
<p>Wow. It looks rather large with all of those comments.  Here is a version without the comments:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">Function</span>.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">debounce</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>threshold<span style="color: #339933;">,</span> execAsap<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> func <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> timeout<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">function</span> debounced <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> obj <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> args <span style="color: #339933;">=</span> arguments<span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">function</span> delayed <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>execAsap<span style="color: #009900;">&#41;</span>
                func.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span>obj<span style="color: #339933;">,</span> args<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            timeout <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">;</span> 
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>timeout<span style="color: #009900;">&#41;</span>
            clearTimeout<span style="color: #009900;">&#40;</span>timeout<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>execAsap<span style="color: #009900;">&#41;</span>
            func.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span>obj<span style="color: #339933;">,</span> args<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        timeout <span style="color: #339933;">=</span> setTimeout<span style="color: #009900;">&#40;</span>delayed<span style="color: #339933;">,</span> threshold <span style="color: #339933;">||</span> <span style="color: #CC0000;">100</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>If you prefer not to augment the native objects, here&#8217;s a stand-alone version:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> debounce <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>func<span style="color: #339933;">,</span> threshold<span style="color: #339933;">,</span> execAsap<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> timeout<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">function</span> debounced <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> obj <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> args <span style="color: #339933;">=</span> arguments<span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">function</span> delayed <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>execAsap<span style="color: #009900;">&#41;</span>
                func.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span>obj<span style="color: #339933;">,</span> args<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            timeout <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">;</span> 
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>timeout<span style="color: #009900;">&#41;</span>
            clearTimeout<span style="color: #009900;">&#40;</span>timeout<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>execAsap<span style="color: #009900;">&#41;</span>
            func.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span>obj<span style="color: #339933;">,</span> args<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        timeout <span style="color: #339933;">=</span> setTimeout<span style="color: #009900;">&#40;</span>delayed<span style="color: #339933;">,</span> threshold <span style="color: #339933;">||</span> <span style="color: #CC0000;">100</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Example uses:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// using debounce in a constructor or initialization function to debounce </span>
<span style="color: #006600; font-style: italic;">// focus events for a widget (onFocus is the original handler):</span>
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">debouncedOnFocus</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #000066;">onFocus</span>.<span style="color: #660066;">debounce</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">500</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputNode</span>.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'focus'</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">debouncedOnFocus</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
<span style="color: #006600; font-style: italic;">// to coordinate the debounce of a method for all objects of a certain class, do this:</span>
MyClass.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">someMethod</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #009966; font-style: italic;">/* do something here, but only once */</span>
<span style="color: #009900;">&#125;</span>.<span style="color: #660066;">debounce</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">100</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// execute at start and use a 100 msec detection period</span>
&nbsp;
&nbsp;
<span style="color: #006600; font-style: italic;">// the dojo way to coordinate the debounce of a method for all objects of a certain class</span>
<span style="color: #006600; font-style: italic;">// (using the stand-alone version)</span>
dojo.<span style="color: #660066;">declare</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'MyClass'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// other members go here</span>
&nbsp;
    someMethod<span style="color: #339933;">:</span> debounce<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #009966; font-style: italic;">/* do something here, but only once */</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">100</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// execute at start and use a 100 msec detection period</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
<span style="color: #006600; font-style: italic;">// wait until the user is done moving the mouse, then execute</span>
<span style="color: #006600; font-style: italic;">// (using the stand-alone version)</span>
document.<span style="color: #660066;">onmousemove</span> <span style="color: #339933;">=</span> debounce<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #009966; font-style: italic;">/* do something here, but only once after mouse cursor stops */</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">250</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p><strong>Let me know if you find this useful in <em>your</em> projects!</strong></p>
<p>P.S.  The mission-critical project was a success!</p>
]]></content:encoded>
			<wfw:commentRss>http://unscriptable.com/2009/03/20/debouncing-javascript-methods/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
	</channel>
</rss>

