ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

NocoBase Cache 缓存 API 完全指南:从基本方法到高级对象缓存操作

2026/9/13 17:42:36 拓冰建站 浏览量
NocoBase Cache 缓存 API 完全指南:从基本方法到高级对象缓存操作 NocoBase Cache 缓存 API 完全指南从基本方法到高级对象缓存操作【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobaseNocoBase 的 Cache 模块基于 node-cache-manager 封装为插件开发和应用运行提供了一套完整的缓存能力。本文以Cache实例 API 为核心系统讲解get/set/del/wrap等基本方法深入剖析wrapWithCondition()条件缓存、setValueInObject()等对象级缓存操作并辅以仓库源码与测试用例佐证帮助读者在插件或业务中正确、高效地使用缓存。概述Cache 在 NocoBase 中的定位在 NocoBase 中缓存能力由两层抽象构成CacheManager缓存管理器负责注册 Store缓存方式、创建与获取 Cache 实例参见 cache-manager.md 与源码 cache-manager.ts。CacheNocoBase 封装的具体缓存实例类提供get()、set()、del()等实际操作方法本文聚焦于这一层。每个Cache实例有唯一的name标识可作为不同模块的命名空间同时支持可选的prefix所有 key 会自动加上prefix:前缀避免多模块间 key 冲突。基本方法Cache的基本方法绝大多数直接委托给底层 node-cache-manager 的 store 实现可参考 node-cache-manager 文档获取更多细节。完整方法清单如下get(key)— 获取缓存值set(key, value, ttl?)— 设置缓存值可选过期时间del(key)— 删除指定 keyreset()— 清空当前 Cache 实例的全部缓存wrap(key, fn, ttl?)— 缓存未命中时执行回调并写入缓存mset(entries, ttl?)— 批量写入mget(...keys)— 批量读取mdel(...keys)— 批量删除keys(pattern?)— 列出所有 key部分 store 可能不支持ttl(key)— 查询 key 剩余过期时间从源码 cache.ts 可以看出所有方法在调用底层 store 之前都会经过key()方法统一加上前缀key(key: string): string { return this.prefix ? ${this.prefix}:${key} : key; }也就是说当 Cache 实例设置了prefix时cache.set(user:1, value)实际写入的是prefix:user:1这个 key。基本用法示例// 设置缓存TTL 单位为毫秒 await cache.set(user:1, { name: John }, 3600_000); // 获取缓存 const user await cache.get(user:1); // 删除缓存 await cache.del(user:1); // 清空当前实例所有缓存 await cache.reset();注意NocoBase 应用级app.cache的 TTL 参数单位是秒参见 插件开发文档 cache.md 中{ ttl: 3600 }的写法而 Cache 实例 API 底层类型为Milliseconds实际单位为毫秒使用前请确认所在上下文的约定。wrap读缓存-兜底执行-回写缓存wrap()是缓存最常见的“读穿”模式封装先尝试从缓存读取命中则直接返回未命中则执行回调函数并把结果写入缓存后返回。const data await cache.wrap(user:1, async () { // 该回调只在缓存未命中时执行 return await this.fetchUserFromDatabase(1); }, 3600_000);批量操作// 批量设置 await cache.mset([ [key1, value1], [key2, value2], ]); // 批量获取返回顺序与入参一致 const values await cache.mget(key1, key2); // 批量删除 await cache.mdel(key1, key2);keys / ttl// 获取所有 key const allKeys await cache.keys(); // 获取 key 的剩余过期时间 const remainingTTL await cache.ttl(user:1);在源码 cache.ts 中keys()返回时会把缓存 key 中的name:命名空间前缀剥离方便使用者拿到的 key 与传入时保持一致。其他方法面向条件与对象场景的高级封装除上述与 node-cache-manager 一一对应的基本方法外NocoBase 在Cache类上额外扩展了三类“其他方法”分别解决条件缓存、对象局部读写两类高频问题。wrapWithCondition()按条件决定是否使用缓存wrapWithCondition()的功能与wrap()类似但可以通过条件决定“要不要使用缓存结果”以及“要不要缓存本次结果”。async wrapWithConditionT( key: string, fn: () T | PromiseT, options?: { // 外部参数控制是否使用缓存结果 useCache?: boolean; // 通过数据结果决定是否缓存 isCacheable?: (val: unknown) boolean | Promiseboolean; ttl?: Milliseconds; }, ): PromiseT {参数说明参数类型说明keystring缓存 keyfn() T \| PromiseT数据获取回调仅在缓存未命中或useCache为false时执行useCacheboolean外部开关设为false时即使有缓存也会重新执行fn但仍可能把新结果写入缓存isCacheable(val) boolean \| Promiseboolean结果校验函数返回false表示本次结果不写入缓存ttlMilliseconds写入缓存时的过期时间从源码实现 cache.ts 可以清晰看到执行逻辑useCache false时直接执行fn()并返回结果否则先get(key)命中则直接返回缓存值未命中则执行fn()用isCacheable(result)判断结果是否可缓存不可缓存则直接返回结果、不写缓存可缓存则set(key, result, ttl)后返回结果。典型使用场景缓存第三方接口或数据库查询结果但只有当结果是“成功且合法”时才缓存失败结果不缓存避免把错误数据长期滞留在缓存中。const data await cache.wrapWithCondition( user:1, async () { return await this.fetchUserFromDatabase(1); }, { // 外部参数控制是否使用缓存结果 useCache: true, // 设为 false 时即使有缓存也会重新执行函数 // 通过数据结果决定是否缓存 isCacheable: (value) { // 比如只有成功的结果才缓存 return value !value.error; }, ttl: 3600_000, }, );对象缓存操作setValueInObject / getValueInObject / delValueInObject当缓存的内容是对象时往往只需要修改其中一个属性。如果每次都走get()后整体改完再set()不仅代码繁琐还存在并发覆盖风险。NocoBase 为此提供了三个对象级操作方法async setValueInObject(key: string, objectKey: string, value: unknown) async getValueInObject(key: string, objectKey: string) async delValueInObject(key: string, objectKey: string)从源码实现 cache.ts 可以看出这三个方法本质上是“读对象 → 改属性 → 回写对象”的封装async setValueInObject(key: string, objectKey: string, value: unknown) { const object (await this.get(key)) || {}; object[objectKey] value; await this.set(key, object); } async getValueInObject(key: string, objectKey: string) { const object (await this.get(key)) || {}; return object[objectKey]; } async delValueInObject(key: string, objectKey: string) { const object (await this.get(key)) || {}; delete object[objectKey]; await this.set(key, object); }需要注意get()未命中时这三个方法会把对象初始化为{}因此setValueInObject可以直接在空缓存上“原地”构建对象无需先手动set一个空对象。使用示例// 设置对象的某个属性 await cache.setValueInObject(user:1, name, John); await cache.setValueInObject(user:1, age, 30); // 获取对象的某个属性 const name await cache.getValueInObject(user:1, name); // John // 删除对象的某个属性 await cache.delValueInObject(user:1, age);源码与测试印证仓库 packages/core/cache/src/cache.ts 是 Cache 类的完整实现而 packages/core/cache/src/tests/cache.test.ts 则对该类的方法行为做了系统性验证包括set/get/del的基本读写删行为should set and get value、should del valuemset/mget/mdel的批量操作与顺序返回should mset and mget values、should mdel valueskeys()的返回结果should get all keys对象操作的读写行为should set and get value in object用例中先getValueInObject取出属性a为1再setValueInObject将其改为2后再次读取验证。这些测试直接印证了文档所述的 API 行为读者可在本地运行测试加深理解cd packages/core/cache yarn vitest run src/__tests__/cache.test.ts在插件与中间件中的落地方式在实际项目中缓存通常通过以下入口获取应用级默认缓存app.cache可直接set/get/del请求上下文缓存ctx.cache在中间件或资源操作中访问参见 插件开发文档 cache.md自定义缓存实例通过app.cacheManager.createCache({ name, prefix, store })创建独立命名空间再用app.cacheManager.getCache(name)获取完整参数说明见 cache-manager.md。典型中间件用法async (ctx, next) { let data await ctx.cache.get(custom:data); if (!data) { // 缓存未命中从数据库获取 data await this.getDataFromDatabase(); // 存入缓存有效期 1 小时 await ctx.cache.set(custom:data, data, { ttl: 3600 }); } await next(); }注意事项内存缓存上限memory store 基于 lru-cache默认max为 2000见 cache-manager.ts使用时可结合数据规模调整max避免内存溢出缓存失效策略数据更新时记得删除或更新相关缓存避免脏数据Key 命名规范建议使用有意义的命名空间与前缀如module:resource:id配合 Cache 实例的prefix使用更佳TTL 设置根据数据更新频率合理设置 TTL在性能与一致性之间取平衡Redis 连接使用 Redis 时需正确配置连接参数、密码并在应用退出时通过cacheManager.close()关闭连接。【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考