The previous definition for cachedGet is complicated. This factors the complexity out into a couple of function-making functions that could be used for different purposes, or combined in different ways.

Results

function memoizedContinuation(fn) {
    var cache = {};
    return function(key, k) {
        if (key in cache)
            k(cache[key]);
        else
            fn(key, k);
    }
}
function consolidateContinuations(fn) {
    var queues = {};
    return function(key, k) {
        if (key in queues)
            queues[key].push(k);
        else {
            var queue = queues[key] = [k];
            fn(key, function(value) {
                while (queue.length)
                    queue.shift().call(this, value);
                delete queues[key];
            });
        }
    }
}
$.cachedGet = consolidateContinuations(memoizedContinuation($.get));
$.cachedGet('services/random', log); $.cachedGet('services/random', log); $.cachedGet('services/echo/1', log); $.cachedGet('services/echo/2', log); $.cachedGet('services/random', log);