前端装饰器函数

147 阅读1分钟

防抖装饰器

// 装饰器的封装function debounce(delay) {  return function(target, key, descriptor) {    const originalMethod = descriptor.value;    let timer;    descriptor.value = function(...args) {      clearTimeout(timer);      timer = setTimeout(() => {        originalMethod.apply(this, args);      }, delay);    };    return descriptor;  };}
当我们某个函数需要进行防抖处理时
@debounce(500)submit() {}@debounce(500)handleChange() {}@debounce(500)handleFilter() {}

节流装饰器

function throttle(delay) {  return function(target, key, descriptor) {    const originalMethod = descriptor.value;    let timer;    let lastExecTime = 0;    descriptor.value = function(...args) {      const now = Date.now();      if (now - lastExecTime >= delay) {        lastExecTime = now;        originalMethod.apply(this, args);      } else {        clearTimeout(timer);        timer = setTimeout(() => {          originalMethod.apply(this, args);        }, delay);      }    };    return descriptor;  };}

@throttle(200)handleScroll() {}@throttle(200)handleResize() {}

日志输出装饰器

日志的输出是很重要的,尤其是在 Nodejs 端,日志输出会通过 pm2 等工具,记录在一些日志文件里,尤其是一些比较公用的工具函数,更是非常重要,一般需要记录这些内容

  • 执行的函数名称

  • 执行时传入的参数

  • 执行后获取到的结果

    function log(target, key, descriptor) { const originalMethod = descriptor.value; descriptor.value = function(...args) { console.log(Entering ${key} with arguments:, args); const result = originalMethod.apply(this, args); console.log(Exiting ${key} with result:, result); return result; }; return descriptor;}

使用的时候

class Common {    @log()    commonRequest(url, params) {        return request(url, params)    }}const common = new Common()common.commonRequest('http://xxx.com', { name: 'l' })Entering commonRequest with arguments: ['http://xxx.com', { name: 'l' }]Exiting commonRequest with result: { 结果 }

错误处理装饰器

跟日志装饰器一样,错误其实也是日志的一部分,错误日志非常重要,因为 Nodejs 的线上报错,大部分都需要通过查日志来进行定位,所以我们也可以封装一个错误的处理装饰器~

function errorHandler(target, key, descriptor) {  const originalMethod = descriptor.value;  descriptor.value = function (...args) {    try {      originalMethod.apply(this, args);    } catch (error) {      console.error(`Error occurred in ${key}:`, error);    }  };  return descriptor;}

使用的时候

class Common {    @log()    commonRequest(url, params) {        return request(url, params)    }}const common = new Common()common.commonRequest('http://xxx.com', { name: 'l' })Error occurred in commonRequest: Request Error

权限校验装饰器

权限的校验在前端一般都不用装饰器,但是在 Nodejs 管理接口时,涉及到权限校验时,用装饰器是非常的方便的

function authenticated(target, key, descriptor) {  const originalMethod = descriptor.value;  descriptor.value = function(...args) {    if (isAuthenticated()) {      originalMethod.apply(this, args);    } else {      console.log('Unauthorized access!');    }  };  return descriptor;}

使用的时候,这样就只有 admin 的身份可以访问这个接口了~

class User {      @Get('/xx/xx')    @authenticated('admin')    getUser() {}}

计时装饰器

如果有一天,你们需要埋点,计算一些比较重要函数的运行性能时,那么你肯定需要计算这些函数的执行时间是多少,这时候封装一个计时装饰器会让你非常方便~

function timing(target, key, descriptor) {  const originalMethod = descriptor.value;  descriptor.value = function(...args) {    const start = performance.now();    const result = originalMethod.apply(this, args);    const end = performance.now();    console.log(`Execution time of ${key}: ${end - start} milliseconds`);    return result;  };  return descriptor;}

使用时

class Common {    @timing()    commonRequest(url, params) {        return request(url, params)    }}const common = new Common()common.commonRequest()Execution time of commonRequest: 20 milliseconds

缓存装饰器

这个装饰器适用在某一些场景,如果你有一个函数是用来计算值的,并且计算的过程非常复杂非常耗时间,那我建议你可以把这些计算结果储存起来,而不是每次都重新计算,这能大大提升你的计算性能~

function cache(target, key, descriptor) {  const originalMethod = descriptor.value;  const cache = new Map();  descriptor.value = function(...args) {    const cacheKey = JSON.stringify(args);    if (cache.has(cacheKey)) {      return cache.get(cacheKey);    }    const result = originalMethod.apply(this, args);    cache.set(cacheKey, result);    return result;  };  return descriptor;}

使用时

class Compute() {    @cache()    run(num1, num2) {        // 这里举个简单例子        return num1 + num2    }}const c = new Compute()c.run(1, 2) // 3 首次计算c.run(1, 2) // 3 接下来都从缓存中拿

参数校验装饰器

在老项目中,无法用到 typescript 这么好的东西时,对于一些函数执行时,有必要用装饰器对传进来的参数的类型进行校验没办法,没有 typescript 真难受啊

function validateArgs(...types) {  return function (target, key, descriptor) {    const originalMethod = descriptor.value;    descriptor.value = function (...args) {      for (let i = 0; i < types.length; i++) {        const type = types[i];        const arg = args[i];        if (typeof arg !== type) {          throw new Error(`Invalid argument type at index ${i}`);        }      }      originalMethod.apply(this, args);    };    return descriptor;  };}

使用的时候需要传入某个参数的类型限制

class Common {    @validateArgs(['string', 'object'])    commonRequest(url, params) {        return request(url, params)    }}const common = new Common()common.commonRequest(123, 123) // 报错