Hacker News new | ask | show | jobs
by mdkess 4590 days ago
Underscore has a nifty function, _.debounce, which given a function f, returns a version of the function that behaves as the one in your interview question. http://underscorejs.org/#debounce Even if not using libraries, it would be nice to abstract that into its own function when you inevitably want to use it again in some other control.

The code is pretty simple - very similar to what you did:

	  function (func, wait, immediate) {
	    var timeout, args, context, timestamp, result;
	    return function() {
	      context = this;
	      args = arguments;
	      timestamp = new Date();
	      var later = function() {
		var last = (new Date()) - timestamp;
		if (last < wait) {
		  timeout = setTimeout(later, wait - last);
		} else {
		  timeout = null;
		  if (!immediate) result = func.apply(context, args);
		}
	      };
	      var callNow = immediate && !timeout;
	      if (!timeout) {
		timeout = setTimeout(later, wait);
	      }
	      if (callNow) result = func.apply(context, args);
	      return result;
	    };
	  }
2 comments

I'm guessing underscore's throttle function would be the better way, if underscore is available.
Thanks for posting this. I'd written my own ad-hoc version of _.debounce for a web app, but the difference between throttle and debounce was totally lost on me. (If anyone else is slow today and doesn't immediately get it from reading the Underscore docs, there's a very clear comparison here[1].)

Empirically, I can't type fast enough (sustained) for throttle to be better than debounce here — there are frequent 200ms gaps in my key presses. This is part of why I was confused. I thought I was typing very quickly, definitely faster than 43wpm == five keystrokes per second, but apparently I slow down to think now and then. My code seemed to behave like _.throttle already, but changing the timeout from 200ms to 2sec made it clear that it wasn't.

But I'm switching to _.throttle, partly in case someone is a faster typist than me, and partly because it makes a leading-edge call, which may give a feeling of greater responsiveness.

1. http://drupalmotion.com/article/debounce-and-throttle-visual...

As other comments have pointed out, `_.debounce` is the correct answer. Here's the bit from the docs that always reminds me when to use `_.debounce` over throttle:

  _.debounce: [...] Useful for implementing behavior that
  should only happen after the input has stopped arriving.
http://underscorejs.org/#debounce
That bit from the Underscore docs is only a suggestion, and one that Google, for example, certainly doesn't follow. Try typing a search query so fast you don't get suggestions until you're finished. It's hard to do!

Right after your quote, the docs add: "For example: rendering a preview of a Markdown comment, recalculating a layout after the window has stopped being resized..." These operations can both be very expensive on the client side — layout is slow — and can also distract the user if they make stuff jump around on the page. The downsides of doing these updates too often are more clear than for a simple autocomplete.

Throttle is different, it's a rate limiter, whereas debounce just measures delays between calls. With throttle, the server request would be made every 200ms rather than 200ms after the user stops typing. From a user experience though, throttle feels like a better way to approach this, since it would let you update the list at a measured pace, but it would be incorrect for the problem as described.
Right, from a UX perspective, throttle makes more sense due to more constant feedback. You want the user to realize that it is a live search before they finish typing. Else, they'll just type the entire query.

But obviously, in this case, the interviewer specifically outlined requirements that would make debounce the better choice than throttle.

Good point. I've generally used debounce for live search, and throttle for window resizing, among other things. In hindsight throttle is perhaps better for live search as well.
For window resizing, i'd actually use debounce. Most times, a user resizes a window with a predetermined size in mind -- they want to show something behind the window, or want to make the window fill an existing space.

In that case, showing live updates in the window during resizing might not be worth it.

This is precisely what I would have suggested I would use if I were asked such a question.
Libraries are the solution, +1. A handcoded solution to this would make me cry.
Wow. A library to wrap setinterval or settimeout? Given the use of "this" in his answer is painful, core JavaScript is already loaded and in IMO more maintainable than 3rd party libraries. In this thread alone there are arguments about what to use from the library. If I were the interviewer I wouldn't hire that answer either. I want a developer who can code his way out of a box, not ignore the box.