使用_.memoize()和_.debounce()

时间:2013-12-23 15:30:56

标签: javascript underscore.js

我想去除每个特定页面调用的渲染功能 - 渲染不同的页面会分别去抖动。 memoize函数应该可以解决问题,但它无法正常工作。

var renderPage_underscore = function(pageNo){
  var debouncer = _.memoize(
    // memoize function
    _.debounce(
      // debounced function
      function () {
        // Do renderPage() work here
        document.getElementById("underscore").innerHTML += 
            '<br />' + pageNo + '@' +   new Date().getTime();
      },
      1000, // delay
      true
    ),
    // memoize hash function
    function (pageNo) {
        return pageNo;
    }
  );
  return debouncer(pageNo);
}; 

任何想法? http://jsfiddle.net/Zq8Wd/1/

2 个答案:

答案 0 :(得分:2)

以这种方式使用_.memoize()的问题在于它缓存返回值,而不是副作用。如果您想使用_.memoize()来解决此问题,您可能需要执行以下操作:

rp = _.memoize(function (pageNo) {
    return _.debounce(function () {
        document.getElementById("underscore").innerHTML +=
            '<br />' + pageNo + '@' + new Date().getTime();
    }, 1000, true);
});

rp(1)();
rp(2)();

更新了JSFiddle

答案 1 :(得分:0)

我想出了这个:

/**
 * Memoizes and debounces a function. i.e., returns a new function, that when invoked,
 * returns a Promise that will resolve after `delay` ms unless invoked repeatedly,
 * in which case the last promise will be rejected and the delay will be reset. If the 
 * result has already been computed, will resolve instantly.
 * 
 * @param {Function} func Function to memoize+debounce
 * @param {Number} delay Delay in milliseconds
 * @param {Function} serialize Function used to resolve the cache key
 * @return {Function} Memoized+debounced function.
 */
function membounce(func, delay=333, serialize = x => x) {
    let cache = new Map();
    let timer, cancel, lastKey;
    return (...args) => {
        let key = serialize.call(func, ...args);
        if(timer) {
            clearTimeout(timer);
            cancel(new Error('Debounced'));
            cache.delete(lastKey);
        }
        if(cache.has(key)) {
            return cache.get(key);
        }
        let promise = new Promise((resolve,reject) => {
            cancel = reject;
            timer = setTimeout(() => {
                let result = func(...args);
                resolve(result);
                timer = null;
            }, delay);
        });
        cache.set(key, promise);
        lastKey = key;
        return promise;
    };
}

总是返回Promise,因此您可以等待它解决,并忽略任何拒绝,这意味着该值已被去抖动/未计算。