Integrando RxJS com Interceptores no NestJS

RxJS e Intercepotres

RxJS é uma biblioteca de programação reativa baseada no padrão Observer, versão JavaScript do ReactiveX. Oferece operadores para manipulação de fluxos de dados assíncronos como eventos de UI, requisições de rede e temporizadores. Seu núcleo utiliza Observables para representar fluxos de dados, com operadores para transformação e combinação de valores.

Criação de Projeto e Interceptor

nest new projeto-interceptor -p npm
nest g interceptor tempo --flat --no-spec
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import { Observable, tap } from 'rxjs';

@Injectable()
export class TempoInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const inicio = Date.now();
    return next.handle().pipe(
      tap(() => console.log(`Execução: ${Date.now() - inicio}ms`))
    );
  }
}
@Controller()
export class AppController {
  @Get()
  @UseInterceptors(TempoInterceptor)
  endpointRaiz() {
    return this.appService.obterMensagem();
  }
}

Operador Map

import { map } from 'rxjs';

@Injectable()
export class FormatarInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      map(dados => ({
        status: 200,
        mensagem: 'sucesso',
        dados
      }))
    );
  }
}

Operador Tap

import { tap } from 'rxjs';

@Injectable()
export class RegistroInterceptor implements NestInterceptor {
  constructor(private servico: AppService) {}
  
  private logger = new Logger(RegistroInterceptor.name);

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      tap((dados) => {
        this.servico.atualizarCache();
        this.logger.log(`Registro: ${JSON.stringify(dados)}`);
      })
    );
  }
}

Operador CatchError

import { catchError, throwError } from 'rxjs';

@Injectable()
export class ErroInterceptor implements NestInterceptor {
  private logger = new Logger(ErroInterceptor.name);

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      catchError(erro => {
        this.logger.error(erro.mensagem, erro.rastro);
        return throwError(() => erro);
      })
    );
  }
}

Operador Timeout

import { timeout, catchError } from 'rxjs';

@Injectable()
export class LimiteTempoInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      timeout(4000),
      catchError(erro => {
        if (erro.name === 'TimeoutError') {
          return throwError(() => new RequestTimeoutException());
        }
        return throwError(() => erro);
      })
    );
  }
}

Intercepter Global

// main.ts
app.useGlobalInterceptors(new TempoInterceptor());

// app.module.ts
providers: [
  {
    provide: APP_INTERCEPTOR,
    useClass: TempoInterceptor
  }
]

Tags: RxJS NestJS Interceptor Observable OperadoresRxJS

Publicado em 6-12 21:57 por Thomas