再谈函数节流与防抖 - 利用装饰器 @decorator 来实现

距离 第一次听到 节流与防抖 已经过去两年的时间,最近也是新看到一道题重新复习下老的知识点,并且提出新的解决方案。

# 先温习一下之前已经知道的经典方法:
// 节流 高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率
exports.throttle = function (fn, limit = 1000) {
    let flag = true;
    return function () {
      if (!flag) {
        return;
      }
      flag = false;
      setTimeout(() => {
        fn.apply(this, arguments);
        flag = true;
      }, limit);
    };
  }

// 防抖 触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
exports.debounce = function (fn, limit = 1000) {
    let flag = null;
    return function () {
      clearTimeout(flag);
      flag = setTimeout(() => {
        fn.apply(this, arguments);
      }, limit);
    };
  }
# 下面抛出新抛出的问题,如何用 @decorator装饰器 来实现呢?

装饰者模式就是动态的给类或对象增加功能的设计模式。虽然在浏览器中还没有被实现,但在TypeScript里已做为一项实验性特性予以支持。

安装TS、调试步骤之类的过程略去,可以参考handbook;下面小记一下decorator的重点:Decorators的实现使用了ES5的 Object.defineProperty 方法,这三个参数也和这个方法的参数一致。装饰器的本质就是一个函数语法糖,通过Object.defineProperty来修改类中一些属性,descriptor参数也是一个对象,是针对key属性的描述符,里面有控制目标对象的该属性是否可写的writable属性等。

function throttle(limit: number = 0) {
    let flag = true
    return (target: any, key: string, descriptor: any) => {
        let func = descriptor.value
        descriptor.value = async (...args: any[]) => {
            if(!flag) return 
            flag = false
            try {
                func.apply(this, ...args)
            } catch (error) {
                console.log(error)    
            }
            if (!limit) return flag = true
            setTimeout(() => {
                flag = true
            }, limit);
        }
    }
}

class TestD{
    @throttle(2000)
    fn() {
      console.log('fn')
    }
}

const testd = new TestD()
setInterval(testd.fn,50);

以上便完成了节流装饰器的操作,说好了问节流和防抖,转头就考了装饰器,老阴阳人了。

参考文档:

  • js防抖节流新姿势
  • typescript-handbook - Decorator
  • TS下的装饰者模式(Decorator)

你可能感兴趣的:(再谈函数节流与防抖 - 利用装饰器 @decorator 来实现)