In the browser land, performance is a problem, especially when mouse and touch events are spamming the web application. E.g. Firefox seemingly likes to defer rendering until processing events are done. This causes a problem that if you are spamming the browser's redraw with mouse or touch events as the renderer will stall until your input events are coming down to a manageable pace.

The solution is to throttle those events and libraries such as lodash has a throttle function. Great!

var framerate = 30; // fps

onMouseMoveCallback = _.throttle(function() {  
    // ...
}, 1 / (framerate * 1000));

Problems with throttling user events using an arbitrarily set framerate

Unfortunately it only solves part of the performance problem, and you will need to tweak the framerate value by the millisecond for different renderers. This leads to a user agent sniffing (or more specifically sniffing for rendering engine on the user agent string). It usually looks like this:

var framerate = 30; // default great framerate

var ua = navigator.userAgent.toLowerCase();

// Firefox rendering engine is SLO-O-O-O-O-O-O-O-O-OW!
if (/gecko\//i.test(ua) {  
    framerate = 20; // sucky framerate to cope with events
}
// + need to do this for the other rendering engines, 
// and perhaps OS's as well
// OH MY!

onMouseMoveCallback = _.throttle(function() {  
    // ...
}, 1 / (framerate * 1000));

This doesn't seem like a great solution, it is actually bad because we're forced to test all rendering engines and tweak it as appropriate.

I wonder if we can throttle the user inputes by determining the actual framerate of the browser using other means... I wonder if we could use requestAnimationFrame?

We can have framerate throttling, for reals? OMG!

Actually we can use requestAnimationFrame to throttle the input events and do a graceful low framerate fallback for browsers who don't have it. The basic idea is to discard invocations between animation frames and pass through when an animation frame has run. The fallback is to use your usual arbitrarily set throttle function, with a low enough framerate to work with your old browsers.

Here is a lodash mixin that handles it all for you:

(function() {
    var defaultFrameRate = 20,
        // This is the default fallback throttle function
        framerateThrottle = function(callback) {
            return _.throttle(callback, 1 / (defaultFrameRate * 1000));
        };

    // Feature detection - should have requestAnimationFrame
    if (window.requestAnimationFrame) {
        framerateThrottle = function(callback) {
            var mayUpdate = false,
                update = function() {
                    mayUpdate = true;
                    window.requestAnimationFrame(update);
                };

            // initial update
            window.requestAnimationFrame(update);

            // the function called by, e.g. an input event
            return function() {
                var thisArg = this;
                // discard the invocation when mayUpdate
                // is false (i.e. is throttled)
                if (mayUpdate) {
                    mayUpdate = false;
                    return callback.apply(thisArg, arguments);
                }
            };
        };
    }

    // Mix in the framerate throttle to lodash
    _.mixin({
        framerateThrottle: framerateThrottle
    });
}());

By using this dynamic throttle, for newer versions of browsers, the rate of inputs come in at the same rate as the browser is able to handle them without locking the renderer (like the Firefox's Gecko engine). So now you don't need to set an arbitrary framerate to throttle Chrome because it's already FA-A-A-A-A-AST!

The usage as a lodash mixin is as simple as the usual throttle function:

onMouseMoveCallback = _.framerateThrottle(function() {  
    // ...
});

This framerate throttle is also available as a gist for easy copy and paste. Enjoy!