为什么您的应用运行缓慢(以及如何修复)
您是否曾经等待过界面在点击后重新渲染?或者观察到服务器多次重复响应同一个请求?熟悉吗?那么这篇文章就是为您准备的。数据缓存不仅仅是一种“良好实践”,更是任何 TypeScript 开发者的基本技能,它能让您的应用飞起来,而不是爬行。
今天,我们将探讨如何在 TypeScript 中正确缓存数据:从前端简单的 in-memory 缓存到后端带有 TTL 和 Redis 的高级策略。您将获得可以直接插入到您项目中的现成代码片段。
什么是缓存,为什么在 TypeScript 中需要它?
缓存是一种将常用数据临时存储在快速存储中的技术。我们不必每次都去数据库或远程服务器获取数据,而是保存第一次请求的结果,并在后续请求中直接返回。
优点显而易见:
- 降低响应时间(延迟)——用户在毫秒内获得数据
- 减轻服务器和数据库的负载
- 节省流量和资源
- 支持离线工作(对于前端)
在 TypeScript 中,得益于类型系统,我们可以编写安全且可预测的缓存,不会在运行时崩溃。让我们看看如何实现。
缓存策略:选择正确的方法
在编写代码之前,需要了解您将使用哪种策略。这决定了您的解决方案的效率。
1. In-Memory 缓存(内存缓存)
最简单、最快的方式。数据存储在变量、Map 或对象中。非常适合前端和小型 Node.js 应用。
缺点:页面刷新或服务器重启时数据会丢失。
2. LocalStorage / SessionStorage(浏览器缓存)
适用于前端,需要在会话之间保存数据。非常适合用户设置、令牌和 API 响应缓存。
缺点:同步访问,大小限制(5-10MB)。
3. Redis(服务器端缓存)
后端工业标准。快速、可靠,支持 TTL 和复杂数据结构。通过 ioredis 库与 Node.js 配合良好。
缺点:需要单独的服务(Redis 服务器)。
4. Service Worker + Cache API(PWA)
用于渐进式 Web 应用的高级缓存。允许拦截网络请求并提供缓存响应。非常适合离线模式。
用 TypeScript 编写缓存:从简单到复杂
现在进入实践环节。我将展示几个实现,从基础到高级,使用 TypeScript 泛型。
带 TTL 的简单 In-Memory 缓存
我们从经典开始——内存缓存,自动删除过期条目。
// cache.tsinterface CacheEntry<T> { data: T; expiry: number; // 毫秒时间戳}
class SimpleCache<T> { private store = new Map<string, CacheEntry<T>>();
constructor(private defaultTTL: number = 60000) {} // 默认 60 秒
set(key: string, data: T, ttl?: number): void { const expiry = Date.now() + (ttl ?? this.defaultTTL); this.store.set(key, { data, expiry }); }
get(key: string): T | undefined { const entry = this.store.get(key); if (!entry) return undefined; if (Date.now() > entry.expiry) { this.store.delete(key); return undefined; // 已过期 } return entry.data; }
has(key: string): boolean { return this.get(key) !== undefined; }
clear(): void {