2014-05-23 5 views
5

एक फ़ंक्शन का उपयोग करना जो परिणाम लौटने के लिए कॉल की श्रृंखला बनाता है, जिसे एक बार कोणीय टेम्पलेट में कई बार अनुरोध किया जाता है। उन अनुरोधों के दौरान, परिणाम नहीं बदलेगा, इसलिए फ़ंक्शन के अंदर अतिरिक्त कॉल करने का ओवरहेड अनावश्यक है।फ़ंक्शन कॉल को सीमित करने और परिणाम विंडो को कैश करने के लिए _.memoize और _.throttle का संयोजन?

क्या एक थ्रॉटल फ़ंक्शन बनाना संभव है जो कैश करता है और एक निश्चित प्रतीक्षा समय के भीतर एक ही परिणाम देता है?

नीचे सरलीकृत उदाहरण की रेखाओं के साथ।

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 

जहां तक ​​मैं समझ गया है, _.memoize कैश परिणाम अनिश्चित काल के तर्क पर आधारित है, एक तरह से स्वचालित रूप से समय-समय पर कैश फ्लश करने के लिए नहीं देख सकता। और _.throttle और _.debounce केवल सेट बाधाओं के भीतर फ़ंक्शन को ट्रिगर करते हैं, लेकिन निहित फ़ंक्शन के आउटपुट को वापस न करें।

+0

मैं underscorejs के लिए स्रोत की जाँच की और उन 2 कार्यों को पहले से ही पिछले गणना परिणाम लौटने के लिए, यदि आप चाहते हैं बस के रूप में। – lastoneisbearfood

उत्तर

2

मैंने इसे विस्तारित करने के लिए _.memoize विधि का उपयोग किया और समाप्त होने पर मानों को पुन: संयोजित करने के लिए एक टीटीएल तर्क जोड़ें।

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

धन्यवाद, इसे मिक्सीन के रूप में पंजीकृत करने में बहुत मददगार - मैंने तब से निष्कर्ष निकाला है कि यह अंडरस्कोर कोर में उपलब्ध नहीं है, लेकिन _.memoize विधि को विस्तारित करने के लिए उम्मीदवार के रूप में इसका उल्लेख करेगा –

0

underscorejs source के अनुसार, यह की तरह दोनों _.throttle और _.debounce पिछले गणना के परिणाम लौट कर लग रहा है। तो जैसा कि, वे पहले से ही वही करते हैं जो आप चाहते हैं।

0

ज्ञापन समाप्त नहीं होता है और तर्क के बावजूद थ्रॉटल समान मूल्य देता है।

यहां एक ज्ञात संस्करण को प्राप्त करने के लिए थ्रॉटल और ज्ञापन का संयोजन है जो एक निश्चित अवधि के बाद पुन: संकलित किया जाएगा।

// 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/

संबंधित मुद्दे

 संबंधित मुद्दे