Caching is a fundamental technique to improve the performance and scalability of your applications. In Nest.js, caching can be seamlessly integrated using the built-in cache manager. In this article, we'll explore how to create a custom @Cacheable decorator to simplify caching in your Nest.js services or controllers.
While Nest.js provides powerful caching mechanisms out of the box, applying caching logic directly within your methods can clutter your code. A custom decorator abstracts this logic, making your code cleaner and more maintainable.
Let's start by creating the @Cacheable decorator that we'll use to cache the results of our methods.
import { Cache } from 'cache-manager'; export function Cacheable(cacheKey: string) { return function ( target: any, propertyName: string, descriptor: PropertyDescriptor, ) { const originalMethod = descriptor.value; descriptor.value = async function (...args: any[]) { const cache: Cache = this.cacheManager; if (!cache) { throw new Error( 'Cannot use Cacheable() decorator without injecting the cache manager.', ); } // Try to get cached data try { const cachedResult = await cache.get(cacheKey); if (cachedResult) { return cachedResult; } } catch (error) { console.error(`Cache get error for key: ${cacheKey}:`, error); } // Call the original method if cache miss const result = await originalMethod.apply(this, args); // Set the new result in cache try { await cache.set(cacheKey, result); } catch (error) { console.error(`Cache set error for key: ${cacheKey}:`, error); } return result; }; return descriptor; }; }
Here's how you can apply the @Cacheable decorator to a method in your service:
import { Injectable } from '@nestjs/common'; import { Cacheable } from './cacheable.decorator'; const SETTING_CACHE_KEY = 'settings'; @Injectable() export class SettingsService { // Inject the cache manager constructor(private readonly cacheManager: Cache) {} /** * Retrieves settings from the cache if available, or loads them from the * repository and caches the result. * * @returns A promise that resolves to a `Settings` object. */ @Cacheable(SETTING_CACHE_KEY) async getSettings(): Promise<Settings> { return await this.findAll(); } // ... other methods like findAll() and buildTree() }
To use the cache manager in your application, you need to register it in your module:
import { Module } from '@nestjs/common'; import { CacheModule } from '@nestjs/cache-manager'; import { SettingsService } from './settings.service'; @Module({ imports: [ CacheModule.register({ isGlobal: true, ttl: 300, // Time to live in seconds max: 100, // Maximum number of items in cache }), ], providers: [SettingsService], }) export class AppModule {}
Ensure that you inject the cache manager into any service or controller that uses the @Cacheable decorator:
import { Injectable } from '@nestjs/common'; import { Cache } from 'cache-manager'; @Injectable() export class SettingsService { constructor(private readonly cacheManager: Cache) {} // ... your methods }
By creating a custom @Cacheable decorator, you can keep your methods clean and focus on the core logic, leaving caching concerns to the decorator. This approach enhances code readability and maintainability, making your Nest.js application more efficient and scalable.
Feel free to leave comments or questions below. Happy coding! ?
The above is the detailed content of Enhance Your Nest.js Performance with a Custom `@Cacheable` Decorator. For more information, please follow other related articles on the PHP Chinese website!