JavaScript 中的批处理和缓存

发表于:2020-7-15 14:08

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:rxliuli    来源:博客园

  场景
  最近在生产环境遇到了下面这样一个场景:
  后台在字典表中存储了一些之前需要前后端共同维护的枚举值,并提供根据 type/id 获取字典的 API。所以在渲染列表的时候,有很多列表的字段直接就是字典的 id,而没有经过后台的数据拼装。
  也是吾辈之前写的文章 react 通用列表组件封装 中的那个通用列表在实际使用时遇到的问题之一。
  起初,吾辈解决问题的流程如下
  · 确定字典字段,添加转换后的对象类型接口
  · 将对象列表进行转换得到其中字典字段的所有值
  · 对字典 id 列表进行去重
  · 根据 id 列表从后台获取到所有的字典数据
  · 将获得的字典数据转换为 id => 字典 的 Map
  · 遍历最初的列表,对里面指定的字典字段进行转换
  可以看到,上面的步骤虽然不麻烦,但却十分繁琐,需要定义额外的类型不说,还很容易发生错误。
  思路
  · 使用 异步批处理 + LRU 缓存 优化性能
  · 支持异步 formatter 获得更好的使用体验
  实现异步批处理
  参考实现: batch
  实现批处理的基本思路如下
  · 使用 Map paramCache 缓存传入的 参数 => 剩余调用次数(该参数还需要查询几次结果)
  · 使用 Map resultCache 缓存 参数 => 结果
  · 使用 lock 标识当前是否有函数正在执行
  · 满足以下条件需要等待
  Map 中不包含结果
  目前有其它调用在执行
  还未满最小等待时长(收集调用的最小时间片段)
  · 使用 lock 标识正在执行
  · 判断是否已经存在结果
  如果不存在则执行批处理处理当前所有的参数
  · 从缓存 Map 中获取结果
  · 将 paramCache 中对应参数的 剩余调用次数 -1
  · 判断是否还需要保留该缓存(该参数对应的剩余调用次数为 0)
  不需要则删除
  · 判断缓存的结果是否是 Error
  是的话则 throw 抛出错误
  LRU 缓存
  参考: Wiki 缓存算法, 实现 MemoryCache
  问:这里为什么使用缓存?
  答:这里的字典接口在大概率上是幂等的,所以可以使用缓存提高性能
  问:那么缓存策略为什么要选择 LRU 呢?
  答:毫无疑问 FIFO 是不合理的
  问:那为什么不选择 LFU 算法呢?它似乎能保留访问最频繁的资源
  答:因为字典表并非完全幂等,吾辈希望避免一种可能–访问最多的字典一直没有删除,而它在数据库已经被更新了。
  大致实现思路如下
  使用一个 Map 记录 缓存 key => 最后访问时间
  每次获取缓存时更新最后访问时间
  添加新的缓存时检查缓存数量
  如果超过最大数量,则删除最后访问时间距离现在最长的一个缓存
  添加新的缓存
  Pass: 不要吐槽性能很差啦,这个场景下不会缓存特别多的元素啦,最多也就不到 1000 个吧
  结合高阶函数
  现在,我们可以结合这两种方式了,同时使用 onceOfSameParam/batch 两个高阶函数来优化 根据 id 获取字典信息 的 API 了。
ts
const getById = onceOfSameParam(
batch<[number], Dict>(async (idList) => {
if (idList.length === 0) {
return new Map()
}
// 一次批量处理多个 id
const list = await this.getByIdList(uniqueBy(idList.flat()))
return arrayToMap(
list,
(dict) => [dict.id],
(dict) => dict,
)
}, 100),
)
  支持异步 formatter
  原本想要支持 ListTable 的异步 formatter 函数,但后来想想,如果 slot 里也包含字典 id 呢?那是否 slot 也要支持异步呢?这可是个比较棘手的问题,所以还是不支持好了。
  最终,吾辈在组件与 API 之间添加了 *Service 中间层负责处理数据转换。

本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号