Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining _.memoize and _.throttle to limit function calls and cache a result within a time window?

Using a function that makes a chain of calls to return a result, which is requested several times at once in an Angular template. During those requests, the result will not change, so the overhead of making the extra calls inside the function is unnecessary.

Is it possible to create a throttled function that caches and returns the same result within a certain wait time?

Along the lines of the simplified example below.

var throttleCache = _.memoizeThrottle(function() {
    return _.now();
}, 100);

_.delay(throttleCache, 0); // now + 0ms
_.delay(throttleCache, 10); // now + 0ms
_.delay(throttleCache, 99); // now + 0ms
_.delay(throttleCache, 101); // now + 101ms
_.delay(throttleCache, 150); // now + 101ms

As far as I've understood, _.memoize caches results indefinitely based on the arguments, can't see a way to automatically flush this cache at intervals. And _.throttle and _.debounce only trigger the function within the set constraints, but do not return the output of the contained function.

like image 871
Yann Eves Avatar asked Oct 31 '22 23:10

Yann Eves


1 Answers

I used the _.memoize method to extend it and add a ttl argument, to force recomputing the values when expired.

#!/usr/bin/env coffee

_=require 'underscore'

# Memoize an expensive function by storing its results.
# After ttl time, the value will be recomputed

memoinesic = (func, hasher=_.identity, ttl=0)->

    memoize = ()->

        cache = memoize.cache
        key = hasher.apply(@,arguments)
        now = Date.now()

        if !_.has(cache,key) or now>cache[key].expires

            cache[key] = 
                value: func.apply(@,arguments)
                expires: now+ttl

        cache[key].value

    memoize.cache = {}

    memoize

_.mixin(memoinesic:memoinesic)

# Let's try it!

appendToNow = _.memoinesic(
    (x)-> "#{x}:#{Date.now()}",
    null,
    1000
)

logTimedFoo = _.compose console.log,_.partial appendToNow,'foo'

logTimedFoo()

setInterval logTimedFoo,200
like image 115
TurboHz Avatar answered Nov 08 '22 08:11

TurboHz