Node.js 實現(xiàn)簡單的無侵入式緩存框架的方法
前言
python 的flask.ext.cache 通過注解這樣對方法返回結(jié)果進(jìn)行緩存:
@cache.cached(timeout=300, key_prefix='view_%s', unless=None) def hello(name=None): print 'view hello called' return render_template('hello.html', name=name)
這類實現(xiàn)方式對業(yè)務(wù)邏輯沒有絲毫的侵入性,非常之優(yōu)雅。
最近在做 Node.js 地項目,然而 js ES 7 之前都不支持注解,目前見到的緩存框架雖然在 API 設(shè)計上都很簡潔、很有想法。
可是痛點在于它們都是侵入式的,需要在業(yè)務(wù)邏輯代碼中插入緩存邏輯,這些方式很不優(yōu)雅。
正題
今天花點時間研究下js有沒有辦法,以比較優(yōu)雅地方法實現(xiàn)緩存。
我對緩存框架的訴求:
- 不對原方法進(jìn)行更改
- 能實現(xiàn)對不同參數(shù)地緩存
- 支持緩存時間
我了解到的 js 能力:
- 隱藏參數(shù)arguments可以獲取參數(shù)列表
- prototype 可用來重寫覆蓋原方法
可行性?
看了看 prototype 文檔
直覺告訴我看起來可行,以下是官方的說明:
當(dāng)一個函數(shù)被調(diào)用時,調(diào)用的參數(shù)被保留在類似數(shù)組 "變量" 的參數(shù)中。例如, 在調(diào)用 "myFn (a、b、c)"時, 在myFn 的主體內(nèi)的參數(shù)將包含 3個類似數(shù)組的元素對應(yīng)于 (a、b、c)。 使用鉤子修改原型時,只需通過調(diào)用該函數(shù)的 apply (),將 this 與參數(shù) (調(diào)用狀態(tài)) 傳遞給當(dāng)前行為。這種模式可以用于任何原型,如 Node.prototype、 Function.prototype 等.
var current = Object.prototype.valueOf; // 由于我的屬性 "-prop-value"是交叉性的, 并不總是 // 在同一個原型鏈上,我想要修改 Object.prototype: Object.prototype.valueOf = function() { if (this.hasOwnProperty('-prop-value')) { return this['-prop-value']; } else { // 它看起來不像我的對象之一,因此,讓我們退回到 // 默認(rèn)行為,通過盡可能地復(fù)制當(dāng)前行為來實現(xiàn). // 此apply的行為類似于其他語言中的"super". // 即使 valueOf() 不帶參數(shù), 其他的鉤子可能會帶有. return current.apply(this, arguments); } }
從示例不難看出,我可以在某些條件下通過 apply() 方法調(diào)用函數(shù)原邏輯,某些條件執(zhí)行我需要的新邏輯。
寫個 demo 測試一下
// 重寫Function的原型方法cache Function.prototype.cache = function () { var _self = this; return function() { console.log('arguments', arguments); var key = arguments[0]; if (cache.has(key)) { return cache.get(key) } else { return _self.apply(this, arguments) } } }
定義 cache,當(dāng)且僅當(dāng) key 為 1 時有值
var cache = { has: (key) => { if (key === 1) return true else return false }, get: (key) => { return "cached value " + key } }
定義測試方法
function request(key) { return 'value of ' + key }
應(yīng)用注入
request = request.cache()
執(zhí)行一下
request(2) "value of 2" request(1) "cached value 1"
看到結(jié)果按照預(yù)期輸出,完美!
最后實現(xiàn)
項目引用了 memory-cache
作為基礎(chǔ)緩存庫,實現(xiàn)了相關(guān)的緩存功能。
simple-cache.js const cache = require('memory-cache'); Function.prototype.cache = function (cachekey, time) { var _self = this; return function() { var key = cachekey(arguments); var value = cache.get(key); if (!value) { value = _self.apply(this, arguments) cache.put(key, value, time); } return value; } } var simpleCache = { cache: function(f, cacheKey, cacheTime) { return f.cache(cacheKey, cacheTime); } } module.exports = simpleCache sample.js const cache = require('simple-cache-z').cache; function cachekey(args) { return args[0] } function request(key) { return (new Date()).getTime(); } request = cache(request, cachekey, 5000); console.log('request 1 ', request(1)); setTimeout(() => { console.log('request 2 ', request(2)); }, 1000) setTimeout(()=> { console.log('request 1 ', request(1)) console.log('request 1 ', request(1)) console.log('request 1 ', request(1)) console.log('request 2 ', request(2)); console.log('request 2 ', request(2)); console.log('request 2 ', request(2)); }, 2000); setTimeout(()=> { console.log('request 1 ', request(1)); console.log('request 1 ', request(1)); console.log('request 1 ', request(1)); console.log('request 2 ', request(2)); console.log('request 2 ', request(2)); console.log('request 2 ', request(2)); }, 10000);
輸出結(jié)果
request 1 1563000551142
// 1000 ms
request 2 1563000552150
// 2000 ms
request 1 1563000551142
request 1 1563000551142
request 1 1563000551142
request 2 1563000552150
request 2 1563000552150
request 2 1563000552150
// 10000 ms
request 1 1563000561151
request 1 1563000561151
request 1 1563000561151
request 2 1563000561151
request 2 1563000561151
request 2 1563000561151
大功告成!
今日研究成果
事實證明方案可行,應(yīng)用到我的項目中對執(zhí)行效率和代碼可讀性的提升非常明顯。
我已經(jīng)把框架打成了包,上傳到 npm 倉庫 simple-cache-z
,可通過如下方式引用。
npm install --save simple-cache-z
用法和代碼上傳至 github 倉庫,歡迎提交代碼和 star:
https://github.com/auv1107/simple-cache-nodejs
總結(jié)
以上所述是小編給大家介紹的Node.js 實現(xiàn)簡單的無侵入式緩存框架的方法,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復(fù)大家的!
相關(guān)文章
Node.js+Express.js+TS實現(xiàn)簡單圖床腳本
在這篇博客文章中,我將介紹如何使用 TypeScript 和 Express 框架來編寫一個簡單的圖床腳本,可以將本地圖片上傳到服務(wù)器,并返回圖片的 URL,這樣,你就可以在 Markdown 文檔中方便地引用圖片,而不用擔(dān)心圖片的存儲和管理問題2023-10-10從零開始學(xué)習(xí)Node.js系列教程之SQLite3和MongoDB用法分析
這篇文章主要介紹了Node.js SQLite3和MongoDB用法,結(jié)合實例形式分析了SQLite3和MongoDB數(shù)據(jù)庫的初始化、連接、查詢等操作的實現(xiàn)技巧與相關(guān)注意事項,需要的朋友可以參考下2017-04-04node故障定位頂級技巧動態(tài)追蹤Dynamic?Trace詳解
這篇文章主要為大家介紹了node故障定位頂級技巧動態(tài)追蹤Dynamic?Trace詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09koa2 用戶注冊、登錄校驗與加鹽加密的實現(xiàn)方法
這篇文章主要介紹了koa2 用戶注冊、登錄校驗與加鹽加密的實現(xiàn)方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值 ,需要的朋友可以參考下2019-07-07node.js express中app.param的用法詳解
express.js是nodejs的一個MVC開發(fā)框架,并且支持jade等多種模板。下面這篇文章主要給大家介紹了關(guān)于node.js express中app.param用法的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。2017-07-07基于html5和nodejs相結(jié)合實現(xiàn)websocket即使通訊
HTML5 擁有許多引人注目的新特性,如 Canvas、本地存儲、多媒體編程接口、WebSocket 等等。雖然現(xiàn)在大家把它捧的很火的樣子,但是個人認(rèn)為它還需要其他平臺的支持才能真正的"火起來"2015-11-11