前面給大家發(fā)了一篇文章xxx,給大家介紹了一遍JavaScript中的裝飾器,今天就給大家介紹一下在我項目中用到過的幾個裝飾器的思路吧!
代碼是偽代碼,只是提供個思路,實際上代碼不止這么少。
當我們在一些特殊場景時,需要使用防抖這個優(yōu)化手段來進行優(yōu)化,比如:
這些函數(shù)都可以使用防抖裝飾器來進行性能優(yōu)化,防抖的意思是,當你頻繁執(zhí)行某一個操作時,這個操作只執(zhí)行最后一次,確保不會因為頻繁的執(zhí)行而損耗性能~下面是裝飾器的封裝:
// 裝飾器的封裝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; };}
當我們某個函數(shù)需要進行防抖處理時:
@debounce(500)submit() {}@debounce(500)handleChange() {}@debounce(500)handleFilter() {}
節(jié)流跟防抖是不同的優(yōu)化手段,節(jié)流是保證在一段時間內(nèi)只執(zhí)行一次操作,適用在這些場景中:
下面是裝飾器的封裝:
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; };}
當我們某個函數(shù)需要進行節(jié)流處理時:
@throttle(200)handleScroll() {}@throttle(200)handleResize() {}
日志的輸出是很重要的,尤其是在 Nodejs 端,日志輸出會通過 pm2 等工具,記錄在一些日志文件里,尤其是一些比較公用的工具函數(shù),更是非常重要,一般需要記錄這些內(nèi)容。
下面是裝飾器的封裝:
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: { 結(jié)果 }
跟日志裝飾器一樣,錯誤其實也是日志的一部分,錯誤日志非常重要,因為 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
權(quán)限的校驗在前端一般都不用裝飾器,但是在 Nodejs 管理接口時,涉及到權(quán)限校驗時,用裝飾器是非常的方便的。
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() {}}
如果有一天,你們需要埋點,計算一些比較重要函數(shù)的運行性能時,那么你肯定需要計算這些函數(shù)的執(zhí)行時間是多少,這時候封裝一個計時裝飾器會讓你非常方便。
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
這個裝飾器適用在某一些場景,如果你有一個函數(shù)是用來計算值的,并且計算的過程非常復雜非常耗時間,那我建議你可以把這些計算結(jié)果儲存起來,而不是每次都重新計算,這能大大提升你的計算性能。
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 這么好的東西時,對于一些函數(shù)執(zhí)行時,有必要用裝飾器對傳進來的參數(shù)的類型進行校驗~沒辦法,沒有 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; };}
使用的時候需要傳入某個參數(shù)的類型限制。
class Common { @validateArgs(['string', 'object']) commonRequest(url, params) { return request(url, params) }}const common = new Common()common.commonRequest(123, 123) // 報錯
本文鏈接:http://www.tebozhan.com/showinfo-26-89713-0.html分享能提高開發(fā)效率,提高代碼質(zhì)量的八個前端裝飾器函數(shù)
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: C# 線程池的使用方法