In response to "A JavaScript Function Guard"

July 19th, 2010

Angus Croll just wrote a blog post on "function requests [where] the function only gets invoked after you’ve finally stopped requesting it". This started out as a comment over there, but quickly grew a little long, so I am just going to post it here. Go read his post to get a little context, it's worth your time.

I have used this pattern multiple times, but I never realized I should generalize it. Kudos, Angus! Great code; great read.

Now to the nitpicks :)

Angus implemented this utility as a prototype constructor, but my opinion is that using a closure is more elegant. It takes less lines of code to implement, and more importantly, less lines of code to use.

// Angus' version, with a bug
var resizeMonitor = new FunctionGuard(function (event) {
    if (typeof window.onresizeend === "function")
}, 100);
window.onresize =;

But, it's actually worse than that to use, because you must bind the run method to the resizeMonitor object. If you don't then this will refer to the global object, rather than the resizeMonitor.

// Bug-free version
var resizeMonitor = new FunctionGuard(function (event) {
    if (typeof window.onresizeend === "function")
}, 100);
window.onresize = function () {, arguments);

Making this utility a function that returns another function with state hidden in a closure is easier for end-users.

// Same example, using my version
window.onresize = doLastCallAfter(100, function (event) {
    if (typeof window.onresizeend === "function")

Simulating an onresizeend event, was definitely a cool example. The first thing that I thought of was to automatically logout an inactive user, and protect their privacy.

var logoutAfterInactivity = doLastCallAfter(600000, function () {
    window.location.href = "";
document.body.onmousemove = document.body.onkeydown = logoutAfterInactivity;

And finally, here is my implementation.

function doLastCallAfter(quietTime, fn, context /*, fixed args */) {
    context = context || this;
    function slice(thing, i) {
        return, i || 0);
    var timer, fixedArgs = slice(arguments, 3);
    return function (/* dynamic args */) {
        var dynamicArgs = slice(arguments);
        if (timer !== undefined) clearTimeout(timer);
        timer = setTimeout(function () {
            fn.apply(context, fixedArgs.concat(dynamicArgs));
        }, quietTime);

Awesome utility, Angus!

« Previous Entry

Next Entry »

Recent Entries

Back to the Futu-rr-e: Deterministic Debugging with rr on November 2nd, 2015

Proposal for Encoding Source-Level Environment Information Within Source Maps on July 22nd, 2015

Source Maps are an Insufficient Debugging Format for the Web on June 19th, 2015

A Compact Representation of Captured Stack Frames for SpiderMonkey on April 10th, 2015

Memory Management in Oxischeme on February 22nd, 2015

Naming `eval` Scripts with the `//# sourceURL` Directive on December 5th, 2014

wu.js 2.0 on August 7th, 2014

Come work with me on Firefox Developer Tools on July 8th, 2014

Debugging Web Performance with Firefox DevTools - Velocity 2014 on June 26th, 2014

Beyond Source Maps on March 12th, 2014

Creative Commons License