Node.js 实现简单的无侵入式缓存框架的方法


Posted in Javascript onJuly 21, 2019

前言

python 的flask.ext.cache 通过注解这样对方法返回结果进行缓存:

@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)

这类实现方式对业务逻辑没有丝毫的侵入性,非常之优雅。

最近在做 Node.js 地项目,然而 js ES 7 之前都不支持注解,目前见到的缓存框架虽然在 API 设计上都很简洁、很有想法。

可是痛点在于它们都是侵入式的,需要在业务逻辑代码中插入缓存逻辑,这些方式很不优雅。

正题

今天花点时间研究下js有没有办法,以比较优雅地方法实现缓存。

我对缓存框架的诉求:

  • 不对原方法进行更改
  • 能实现对不同参数地缓存
  • 支持缓存时间

我了解到的 js 能力:

  1. 隐藏参数arguments可以获取参数列表
  2. prototype 可用来重写覆盖原方法

可行性?

看了看 prototype 文档

直觉告诉我看起来可行,以下是官方的说明:

当一个函数被调用时,调用的参数被保留在类似数组 "变量" 的参数中。例如, 在调用 "myFn (a、b、c)"时, 在myFn 的主体内的参数将包含 3个类似数组的元素对应于 (a、b、c)。 使用钩子修改原型时,只需通过调用该函数的 apply (),将 this 与参数 (调用状态) 传递给当前行为。这种模式可以用于任何原型,如 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 {
  // 它看起来不像我的对象之一,因此,让我们退回到 
  // 默认行为,通过尽可能地复制当前行为来实现.
  // 此apply的行为类似于其他语言中的"super".
  // 即使 valueOf() 不带参数, 其他的钩子可能会带有.
  return current.apply(this, arguments);
 }
}

从示例不难看出,我可以在某些条件下通过 apply() 方法调用函数原逻辑,某些条件执行我需要的新逻辑。

写个 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,当且仅当 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
}

应用注入

request = request.cache()

执行一下

request(2)
"value of 2"
request(1)
"cached value 1"

看到结果按照预期输出,完美!

最后实现

项目引用了 memory-cache 作为基础缓存库,实现了相关的缓存功能。

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);

输出结果

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

大功告成!

今日研究成果

事实证明方案可行,应用到我的项目中对执行效率和代码可读性的提升非常明显。

我已经把框架打成了包,上传到 npm 仓库 simple-cache-z ,可通过如下方式引用。

npm install --save simple-cache-z

用法和代码上传至 github 仓库,欢迎提交代码和 star:

https://github.com/auv1107/simple-cache-nodejs

总结

以上所述是小编给大家介绍的Node.js 实现简单的无侵入式缓存框架的方法,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

Javascript 相关文章推荐
jquery隐藏标签和显示标签的实例
Nov 11 Javascript
js实现div的切换特效上一个下一个
Feb 11 Javascript
js中array的sort()方法使用介绍
Feb 20 Javascript
理解javascript回调函数
Dec 28 Javascript
js实现的tab标签切换效果代码分享
Aug 25 Javascript
谈谈JavaScript数组常用方法总结
Jan 24 Javascript
jQuery animate()实现背景色渐变效果的处理方法【使用jQuery.color.js插件】
Mar 15 Javascript
js oncontextmenu事件使用详解
Mar 25 Javascript
Vue.js 中的 v-show 指令及用法详解
Nov 19 Javascript
django使用channels2.x实现实时通讯
Nov 28 Javascript
小谈angular ng deploy的实现
Apr 07 Javascript
vue 导航守卫和axios拦截器有哪些区别
Dec 19 Vue.js
Vue中遍历数组的新方法实例详解
Jul 21 #Javascript
Vue项目中使用WebUploader实现文件上传的方法
Jul 21 #Javascript
jquery插件开发模式实例详解
Jul 20 #jQuery
JS回调函数原理与用法详解【附PHP回调函数】
Jul 20 #Javascript
JavaScript展开操作符(Spread operator)详解
Jul 20 #Javascript
JavaScript剩余操作符Rest Operator详解
Jul 20 #Javascript
微信小程序点击图片实现长按预览、保存、识别带参数二维码、转发等功能
Jul 20 #Javascript
You might like
php中json_encode不兼容JSON_UNESCAPED_UNICODE的解决方案
2016/05/31 PHP
php实现学生管理系统
2020/03/21 PHP
PHP会话操作之cookie用法分析
2016/09/28 PHP
PHP实现移除数组中为空或为某值元素的方法
2017/01/07 PHP
php合并数组并保留键值的实现方法
2018/03/12 PHP
PHP上传图片到数据库并显示的实例代码
2019/12/20 PHP
关于JS数组追加数组采用push.apply的问题
2014/06/09 Javascript
js动态往表格的td中添加图片并注册事件
2014/06/12 Javascript
jquery实现勾选复选框触发事件给input赋值
2015/02/01 Javascript
全面解析Bootstrap排版使用方法(文字样式)
2015/11/30 Javascript
js实现prototype扩展的方法(字符串,日期,数组扩展)
2016/01/14 Javascript
BootStrap实现树形目录组件代码详解
2016/06/21 Javascript
JS正则表达式验证账号、手机号、电话和邮箱是否合法
2017/03/08 Javascript
nodejs批量下载图片的实现方法
2017/05/19 NodeJs
Angular将填入表单的数据渲染到表格的方法
2017/09/22 Javascript
VeeValidate在vue项目里表单校验应用案例
2018/05/09 Javascript
学习React中ref的两个demo示例
2018/08/14 Javascript
layui实现三级联动效果
2019/07/26 Javascript
[59:36]2018DOTA2亚洲邀请赛 4.3 突围赛 Secret vs VG 第二场
2018/04/04 DOTA
在Python的gevent框架下执行异步的Solr查询的教程
2015/04/16 Python
python 简单的绘图工具turtle使用详解
2017/06/21 Python
python删除文本中行数标签的方法
2018/05/31 Python
从DataFrame中提取出Series或DataFrame对象的方法
2018/11/10 Python
python pandas模块基础学习详解
2019/07/03 Python
python 读取二进制 显示图片案例
2020/04/24 Python
Keras自定义IOU方式
2020/06/10 Python
Python编写memcached启动脚本代码实例
2020/08/14 Python
python+appium+yaml移动端自动化测试框架实现详解
2020/11/24 Python
施华洛世奇中国官网:SWAROVSKI中国
2020/06/16 全球购物
什么是SCM(软件配置管理)
2014/08/16 面试题
班会关于环保演讲稿
2013/12/29 职场文书
供货协议书范本
2014/04/22 职场文书
个人工作表现评语
2014/04/30 职场文书
班级团队活动方案
2014/08/14 职场文书
十大冰系宝可梦排名,颜值最高的阿罗拉九尾,第三使用率第一
2022/03/18 日漫
Nginx 配置 HTTPS的详细过程
2022/05/30 Servers