2014-05-23 5 views
5

Verwenden einer Funktion, die eine Kette von Aufrufen zu einem Ergebnis führt, das mehrmals in einer Angular-Vorlage angefordert wird. Während dieser Anfragen ändert sich das Ergebnis nicht, so dass der Mehraufwand für die zusätzlichen Anrufe innerhalb der Funktion nicht notwendig ist.Kombinieren von _.memoize und _.throttle, um Funktionsaufrufe einzuschränken und ein Ergebnis innerhalb eines Zeitfensters zwischenzuspeichern?

Ist es möglich, eine gedrosselte Funktion zu erstellen, die das gleiche Ergebnis innerhalb einer bestimmten Wartezeit zwischenspeichert und zurückgibt?

Entlang der Linien des vereinfachten Beispiels unten.

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 

Soweit ich verstanden habe, auf unbestimmte Zeit _.memoize Caches Ergebnisse auf den Argumenten basiert, kann nicht sehen, wie man automatisch diesen Cache in Abständen zu spülen. Und _.throttle und _.debounce lösen nur die Funktion innerhalb der festgelegten Einschränkungen aus, geben aber nicht die Ausgabe der enthaltenen Funktion zurück.

+0

überprüfte ich die Quelle für Underscore.js und diese zwei Funktionen bereits das letzte berechnete Ergebnis zurück, so wie Sie wollen. – lastoneisbearfood

Antwort

2

Ich habe die _.memoize-Methode verwendet, um sie zu erweitern und ein ttl-Argument hinzuzufügen, um das Neuberechnen der Werte zu erzwingen, wenn sie abgelaufen sind.

#!/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 
+0

danke, sehr hilfreich, dies als Mixin zu registrieren - ich habe festgestellt, dass dies nicht in Underscore-Kern verfügbar ist, aber es wird als ein Kandidat für die Erweiterung der _.memoize-Methode erwähnen –

0

Nach dem underscorejs source sieht es aus wie beide _.throttle und _.debounce DO das Ergebnis der letzten Berechnung zurück. So wie es ist, machen sie schon, was Sie wollen.

0

memoize läuft nicht ab und throttled gibt unabhängig von Argumenten den gleichen Wert zurück.

Hier ist eine Kombination aus Drosselung und Memoize, um eine memoisierte Version der Funktion zu erhalten, die nach einer festen Dauer neu berechnet wird.

// tester to get a combinaison of throttle and memoize. 

var _ = require('lodash'); 

var start = Date.now(); 

var func = function(text) { 
    var toDisplay = "argument " + text + " at " + (Date.now() - start); 
    console.log("executed with", toDisplay); 
    return toDisplay; 
}; 

var getCachedFunc = function(myFuncToCache, cacheDuration, context) { 
    // we need to return a different throttled function for each different parameters so memoize it 
    var memoizedFunction = _.memoize(function() { 
    var myFuncToCacheArguments = arguments; 
    var throttledFunc = _.throttle(myFuncToCache, cacheDuration, {trailing: false}); 
    return function executeThrottledFunction() {return throttledFunc.apply(null, myFuncToCacheArguments);}; 
    }); 

    return function applyMemoizedFunction() { 
    // apply the throttled function 
    return memoizedFunction.apply(context, arguments)(); 
    }; 
}; 

var myCachedFunc = getCachedFunc(func, 4000); 

var callWithArgument1 = function() { 
    console.log("calling with argument 1 at " + (Date.now() - start)); 
    console.log("returned",myCachedFunc('1')); 
}; 

var callWithArgument2 = function() { 
    console.log("calling with argument 2 at " + (Date.now() - start)); 
    console.log("returned",myCachedFunc('2')); 
}; 

callWithArgument1(); 
setTimeout(function() {callWithArgument1();}, 2000); 
setTimeout(function() {callWithArgument2();}, 2200); 
setTimeout(function() {callWithArgument1();}, 5000); 

http://jsfiddle.net/6kq4rt0b/

Verwandte Themen