Caching en TypeScript: Redis, Memcached y soluciones integradas: de la A a la Z
\n\nEl caching es una de las herramientas clave para mejorar el rendimiento de aplicaciones web y servicios. En el ecosistema de TypeScript y Node.js, los desarrolladores pueden elegir entre potentes sistemas externos (Redis, Memcached) y soluciones integradas ligeras. En este artículo, analizaremos los tres enfoques, proporcionaremos ejemplos prácticos de código en TypeScript y ayudaremos a elegir la estrategia óptima para su proyecto.
\n\n¿Por qué es necesario el caching en TypeScript?
\nEl caching permite reducir el tiempo de respuesta del servidor, disminuir la carga en bases de datos y API externas, así como reducir las latencias en solicitudes repetitivas. En TypeScript, que funciona sobre Node.js, el caché es especialmente útil para:
\n- \n
- almacenar resultados de cálculos costosos; \n
- cachear respuestas de API externas; \n
- guardar sesiones de usuarios; \n
- reducir la cantidad de solicitudes a la base de datos. \n
1. Soluciones integradas para caching en TypeScript
\nPara proyectos pequeños o prototipos, se pueden usar las herramientas integradas de Node.js sin instalar paquetes adicionales.
\n\n1.1. Uso de Map
\nLa forma más sencilla es usar un objeto Map o un objeto simple. Sin embargo, este caché solo vive en la memoria de un proceso y se pierde al reiniciar.
// Caché simple basado en Map\nclass SimpleCache<T> {\n private cache = new Map<string, T>();\n\n get(key: string): T | undefined {\n return this.cache.get(key);\n }\n\n set(key: string, value: T): void {\n this.cache.set(key, value);\n }\n\n clear(): void {\n this.cache.clear();\n }\n}\n\n// Ejemplo de uso\nconst cache = new SimpleCache<string>();\ncache.set('user:1', 'Alice');\nconsole.log(cache.get('user:1')); // Alice\n\n1.2. Caché con TTL (Time-To-Live)
\nUna versión más avanzada es un caché con eliminación automática de entradas después de un tiempo determinado.
\n// Caché con TTL\nclass TtlCache<T> {\n private cache = new Map<string, { value: T; expiry: number }>();\n\n get(key: string): T | undefined {\n const item = this.cache.get(key);\n if (!item) return undefined;\n if (Date.now() > item.expiry) {\n this.cache.delete(key);\n return undefined;\n }\n return item.value;\n }\n\n set(key: string, value: T, ttlMs: number): void {\n this.cache.set(key, {\n value,\n expiry: Date.now() + ttlMs,\n });\n }\n}\n\n// Ejemplo\nconst ttlCache = new TtlCache<number>();\nttlCache.set('price', 100, 5000); // vive 5 segundos\nsetTimeout(() => console.log(ttlCache.get('price')), 6000); // undefined\n\n2. Caching con Redis en TypeScript
\nRedis es un popular almacén de datos en memoria que admite estructuras de datos avanzadas, pub/sub y persistencia. Para TypeScript se utiliza el paquete ioredis.
2.1. Instalación y conexión
\nnpm install ioredis\nnpm install @types/ioredis --save-dev\nimport Redis from 'ioredis';\n\nconst redis = new Redis({\n host: 'localhost',\n port: 6379,\n});\n\nredis.on('connect', () => console.log('Connected to Redis'));\nredis.on('error', (err) => console.error('Redis error', err));\n\n2.2. Operaciones básicas set/get
\n// Guardamos un valor\nawait redis.set('user:1:name', 'Alice');\n\n// Obtenemos el valor\nconst name = await redis.get('user:1:name');\nconsole.log(name); // Alice\n\n// Establecemos TTL (en segundos)\nawait redis.setex('session:123', 3600, 'active');\n\n2.3. Trabajo con objetos (JSON)
\n// Guardamos un objeto\nconst user = { id: 1, name: 'Alice', email: 'alice@example.com' };\nawait redis.set('user:1', JSON.stringify(user));\n\n// Leemos y parseamos\nconst r