前言:官方文档在这方面还是没有讲清楚什么使用,怎么应用,只是给了个大概的配置和大致的使用方式,限制在单数据流缓存get请求的数据上面,并没有实质意义上用到缓存的处理。于是博主花了接近一个星期翻看源码以及逐步测试,发现实际上使用真的很简单,这里确实要夸一下nestjs的封装。接下来博主就以验证码缓存来着重介绍其用法。
1、源码分析:
通过官方文档,我们知道要写个拦截器继承CacheInterceptor进行对服务的交互处理,于是让我们查看一下它做了什么操作:
let CacheInterceptor = class CacheInterceptor { constructor(cacheManager, reflector) { this.cacheManager = cacheManager; this.reflector = reflector; async intercept(context, call$) { const key = this.trackBy(context); if (!key) { return call$; try { const value = await this.cacheManager.get(key); if (value) { return rxjs_1.of(value); return call$.pipe(operators_1.tap(response => this.cacheManager.set(key, response))); catch (_a) { return call$; trackBy(context) { const httpServer = this.applicationRefHost.applicationRef; const isHttpApp = httpServer && !!httpServer.getRequestMethod; if (!isHttpApp) { return this.reflector.get(cache_constants_1.CACHE_KEY_METADATA, context.getHandler()); const request = context.getArgByIndex(0); if (httpServer.getRequestMethod(request) !== 'GET') { return undefined; return httpServer.getRequestUrl(request);
1.1、trackBy()
此方法传递一个context上下文进来,通过上下文获取我们请求的对象,如果是get请求,则找到此时在请求阶段promise的CacheKey的值;如果是post或其他请求方式则不做操作。
1.2、intercept()
此方法对服务端回数据制做进一步的处理,通过rxjs的分发机制,我们可以了解到,它分发了我们此次请求回来的response数据,同时也通过构造中的cacheManager来保存了当前的response。更为重要的是根据它自定义的trackBy方法获取了之前的key值,这点很关键。我们后面获取数据时的必要条件。
2、自定义拦截器:
2.1、需求
在我们开始编程的时候必须先理清楚我们需求的功能,我们需要缓存此次的验证码,并且通过key再次获取它进行进一步的验证。
2.2、分别建立两个拦截器:
PutCodeInterceptor
@Injectable() export class PutCodeInterceptor extends CacheInterceptor { trackBy(context: ExecutionContext) { const req = context.switchToHttp().getRequest(); return 'smsKey';
GetCodeInterceptor
@Injectable() export class GetCodeInterceptor extends CacheInterceptor { async intercept(context: ExecutionContext, call$: Observable<any>): Promise<Observable<any>> { const result = await this.cacheManager.get('smsKey'); return call$.pipe(map(data => ({ result })));
分析: PutCodeInterceptor 将key值通过request来进行获取,这里我简单的写死为'smsKey',这样便可以通过CacheIntercepter的 intercept方法获取此key来根据key缓存response。 然后作为再次获取此缓存的value ,再次添加GetCodeInterceptor 重写 CacheIntercepter 的 intercept方法 ,最终通过cacheManager的get()方法获取方才缓存的response,最终可以通过缓存的response来进行判断处理,我这里为了方便起见直接当result返回了。
3、使用:
@Controller('sms') export class SmsController{ constructor(private log: Log, private app: AppService) { } @Get('put') @UseInterceptors(PutCodeInterceptor) async testCode() { const rep: DoctorInfo = { name: '你好', code: this.app.createCode(), return rep; @Post('test') @UseInterceptors(GetCodeInterceptor) async test() {
最终测试效果: