17 comments

[ 5.2 ms ] story [ 46.9 ms ] thread
And if you don't want to add dependency on a whole framework just for that little bit of functionality? It's useful to know how to implement it on its own.
Well the example given is bugged, as if you make updates at 0 and 50, then it never fires the function at 100 for the change that occurred at 50. If I didn't want to rely on the whole framework, I'd copy and paste the tested implementation (and dependencies) in underscore.

Not that it's bad to know how to do it yourself, but I'd make sure my implementation was sound before sharing it as advice.

Underscore is tiny, and there are lots of other goodies you'll probably want to use in there if you look, like _.each(), _.defer(), _.pluck(), _.escape(), and so many more; totally worth it. I installed underscore for backbone, and I have a hard time imagining life without it now, even if I didn't use backbone.
When I'm writing actual web sites I always include underscore. However when writing libraries that I want to distribute on their own I don't want to force unnecessary third party dependencies on end users if it can be avoided. In those cases I have pulled out a single underscores function that I happened to need.
This could make your code behave unpredictably, since you don't really know what events will be used or dropped. For something like a drag handler it's probably not an issue, but it's a little hard to reason about a function whose state depends on when the function was last called. You could easily run into a bug where two pieces of code call a trickle'ed function, expecting it to take an action, and encountering a bug when the two calls are too close.

If polling is what's needed then it makes more sense to use setInterval and have a better guarantee of when things are being run. Or you could stuff events into a buffer and have a function consume them periodically - either way, when you lose an event it's either 1. irrelevant, because polling only cares about the state at time t and not the events, or 2. deterministic, because your consumer function decided to get rid of it.

you probably run into that more with global functions, which this definitely isn't suitable for. but if you trickle a callback that just handles, for example, keydown on a single input, this sort of thing is really useful.
This is one of the great things about JavaScript and functional programming in general. You can create reusable control flow abstractions easily.

Other examples are things like memoizing/caching values, logging, etc.

I am doing validation for username and email from JavaScript with the server similar to the way twitter is doing. I have to make sure that I do not bombard my server for each keystroke and mouse click (in case user decides to copy+paste the email address using the mouse). This is how I did. It works so far but as always it can enhanced. I can share the full source but it is the skeleton to give u the idea. In essence I am waiting for 1300 milliseconds before hitting the server again.

$(emailTextBoxId).keyup(function (event) {

    //executes a function, once, after waiting a specified number of milliseconds
    setTimeout("CheckEmailAddressAvailability()", 1300);
    //stopping bubble
    return false;
});

$(emailTextBoxId).keydown(function (event) {

    safeToPerformEmailCheck = true;
    document.getElementById("ValidEmailAdd").style.display = "none";
    document.getElementById("ExistingEmailAcc").style.display = "none";
    //document.getElementById("InvalidEmailAdd").style.display = "none";
});

$(emailTextBoxId).mouseup(function (event) {

    safeToPerformEmailCheck = true;
    CheckEmailAddressAvailability();
});

Edit: I just saw the examples posted by fellow readers at following links are much better than mine. I am glad I really learned some good stuff today and I will edit my code today as first thing once I go home this eve. Really neat.

http://jsbin.com/ejimok/3/edit

http://jsbin.com/ejimok/5/edit

That's how I do my keypress events. It stores the keypress into a buffer, then only calls the 'search' when a timeout is hit. Calling setTimeout gives you a pointer to the timer, so you can clear the timeout when you get another keypress, thus allowing you to start the timer again. If I tried to send on every keypress, I'd occasionally get out of order packets. Sending them buffered up all at once lets me avoid out of sequence packets, and it reduces the load on the server.
This program has a bug.

Suppose the user is entering the word "hacker" at .101 seconds per character, and your cooldown time is .3, your code will do something like this:

  t=0.000 : 'h' FIRE
  t=0.101 : 'a'
  t=0.202 : 'c'
  t=0.303 : 'k' FIRE
  t=0.404 : 'e'
  t=0.505 : 'r'
If the expensive, rate-limited function is an AJAX call to the server to see if a username is available, for example, you'll want to call again with "hacker" at t=0.6 seconds, not keep displaying the result for "hack" forever.

Actually, the expected behavior isn't sufficiently well-specified to determine whether the code implements it. But I believe many applications of such code will need to take care to avoid the behavior I describe.

As suggested in another comment, I'd use a setInterval (classic JS) or a separate thread (HTML5 or node.js) to periodically check if the function needs to be run, and if so, run it.