Bird
Raised Fist0
NestJSframework~10 mins

Why interceptors add cross-cutting logic in NestJS - Test Your Understanding

Choose your learning style10 modes available
Practice - 5 Tasks
Answer the questions below
1fill in blank
easy

Complete the code to create a basic interceptor class in NestJS.

NestJS
import { Injectable, [1] } from '@nestjs/common';

@Injectable()
export class LoggingInterceptor implements [1] {
  intercept(context: any, next: any) {
    console.log('Before...');
    return next.handle();
  }
}
Drag options to blanks, or click blank then click option'
ANestInterceptor
BController
CService
DModule
Attempts:
3 left
💡 Hint
Common Mistakes
Using Controller or Service instead of NestInterceptor interface.
Forgetting to import the NestInterceptor interface.
2fill in blank
medium

Complete the code to add logic before and after the request handling in an interceptor.

NestJS
intercept(context: any, next: any) {
  console.log('Before...');
  return next.handle().pipe([1](() => console.log('After...')));
}
Drag options to blanks, or click blank then click option'
Afilter
Breduce
Cmap
Dtap
Attempts:
3 left
💡 Hint
Common Mistakes
Using map which changes data instead of just running side effects.
Using filter or reduce which are not for side effects.
3fill in blank
hard

Fix the error in the interceptor code by completing the missing import.

NestJS
import { Injectable, NestInterceptor, ExecutionContext, [1] } from '@nestjs/common';
import { Observable } from 'rxjs';
Drag options to blanks, or click blank then click option'
AController
BService
CCallHandler
Dtap
Attempts:
3 left
💡 Hint
Common Mistakes
Importing unrelated classes like Controller or Service.
Forgetting to import CallHandler causing type errors.
4fill in blank
hard

Fill both blanks to create a logging interceptor that measures execution time.

NestJS
intercept(context: ExecutionContext, next: [1]): Observable<any> {
  const now = Date.now();
  return next.handle().pipe([2](() => console.log(`Execution time: ${Date.now() - now}ms`)));
}
Drag options to blanks, or click blank then click option'
ACallHandler
Btap
Cmap
DController
Attempts:
3 left
💡 Hint
Common Mistakes
Using wrong types for next parameter.
Using map instead of tap for logging.
5fill in blank
hard

Fill all three blanks to create a caching interceptor that stores and returns cached responses.

NestJS
import { Injectable, NestInterceptor, ExecutionContext, [1] } from '@nestjs/common';
import { Observable, of } from 'rxjs';
import { tap } from 'rxjs/operators';

@Injectable()
export class CacheInterceptor implements NestInterceptor {
  private cache = new Map();

  intercept(context: ExecutionContext, next: [2]): Observable<any> {
    const key = context.getHandler().name;
    if (this.cache.has(key)) {
      return [3](this.cache.get(key));
    }
    return next.handle().pipe(tap((value) => {
      this.cache.set(key, value);
    }));
  }
Drag options to blanks, or click blank then click option'
ACallHandler
Cof
Dtap
Attempts:
3 left
💡 Hint
Common Mistakes
Using wrong types for next parameter.
Returning raw data instead of an observable.

Practice

(1/5)
1. What is the main reason to use interceptors in NestJS?
Interceptors help to add logic that applies to many parts of the app without repeating code. Why is this useful?
easy
A. They add shared logic before and after main code, like logging or timing.
B. They replace controllers to handle HTTP requests directly.
C. They store data permanently in the database.
D. They generate frontend UI components automatically.

Solution

  1. Step 1: Understand the role of interceptors

    Interceptors run code before and after the main handler, allowing shared tasks like logging or error handling.
  2. Step 2: Compare with other options

    Controllers handle requests, databases store data, and UI components are unrelated to interceptors.
  3. Final Answer:

    They add shared logic before and after main code, like logging or timing. -> Option A
  4. Quick Check:

    Interceptors add shared logic = A [OK]
Hint: Interceptors wrap main code to add shared tasks [OK]
Common Mistakes:
  • Thinking interceptors handle HTTP requests directly
  • Confusing interceptors with database or UI roles
  • Assuming interceptors replace controllers
2. Which of the following is the correct way to implement an interceptor in NestJS?
easy
A. Implement the NestInterceptor interface and define the intercept() method.
B. Create a class with a handle() method and decorate it with @Controller().
C. Use @Injectable() on a service without any methods.
D. Write a function that returns a promise without any interface.

Solution

  1. Step 1: Recall NestJS interceptor pattern

    Interceptors must implement the NestInterceptor interface and define the intercept() method.
  2. Step 2: Check other options

    Controllers use @Controller() and handle() is not an interceptor method; services need methods; plain functions lack interface.
  3. Final Answer:

    Implement the NestInterceptor interface and define the intercept() method. -> Option A
  4. Quick Check:

    Interceptor interface + intercept() = B [OK]
Hint: Interceptors always implement NestInterceptor with intercept() [OK]
Common Mistakes:
  • Confusing interceptors with controllers or services
  • Missing the intercept() method
  • Not using the NestInterceptor interface
3. Given this interceptor code snippet:
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable, tap } from 'rxjs';

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    console.log('Before handler');
    return next.handle().pipe(
      tap(() => console.log('After handler'))
    );
  }
}

What will be printed to the console when a request is handled?
medium
A. Only After handler
B. Before handler, then After handler
C. Only Before handler
D. No output printed

Solution

  1. Step 1: Analyze the intercept method flow

    The interceptor logs 'Before handler' immediately, then calls next.handle() which runs the main handler.
  2. Step 2: Understand the tap operator

    The tap operator runs after the main handler completes, logging 'After handler'.
  3. Final Answer:

    Before handler, then After handler -> Option B
  4. Quick Check:

    Logs before and after handler = C [OK]
Hint: Logs before then after main handler due to tap() [OK]
Common Mistakes:
  • Thinking only one log prints
  • Confusing order of logs
  • Ignoring the tap() operator effect
4. You wrote this interceptor but it does not log anything:
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';

@Injectable()
export class SilentInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    console.log('Intercepted');
    next.handle();
  }
}

What is the problem?
medium
A. The import statements are incorrect.
B. The console.log statement is after next.handle(), so it never runs.
C. The class is missing the @Controller() decorator.
D. The intercept method does not return the observable from next.handle().

Solution

  1. Step 1: Check the intercept method return

    The intercept method must return the observable from next.handle() to continue the request flow.
  2. Step 2: Identify missing return

    Here, next.handle() is called but its result is not returned, so the request does not proceed and logs may not appear.
  3. Final Answer:

    The intercept method does not return the observable from next.handle(). -> Option D
  4. Quick Check:

    Missing return next.handle() = D [OK]
Hint: Always return next.handle() observable in intercept() [OK]
Common Mistakes:
  • Forgetting to return next.handle()
  • Misplacing console.log after next.handle()
  • Confusing decorators for interceptors
5. You want to measure the time taken by any request handler in your NestJS app. Which interceptor approach correctly adds this cross-cutting timing logic?
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable, tap } from 'rxjs';

@Injectable()
export class TimingInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const start = Date.now();
    return next.handle().pipe(
      tap(() => {
        const elapsed = Date.now() - start;
        console.log(`Request took ${elapsed}ms`);
      })
    );
  }
}
hard
A. This interceptor logs time but does not call next.handle(), so no handler runs.
B. This interceptor measures time only before the handler, missing after completion.
C. This interceptor correctly measures time before and after the handler using tap().
D. This interceptor should use setTimeout instead of tap() to measure time.

Solution

  1. Step 1: Understand timing measurement

    The interceptor records start time before calling next.handle() and uses tap() to run code after the handler completes.
  2. Step 2: Confirm correct usage of RxJS tap()

    The tap() operator runs side effects after the observable emits, so it correctly logs elapsed time after the request finishes.
  3. Final Answer:

    This interceptor correctly measures time before and after the handler using tap(). -> Option C
  4. Quick Check:

    Timing with tap() after handler = A [OK]
Hint: Use tap() after next.handle() to measure elapsed time [OK]
Common Mistakes:
  • Measuring time only before handler
  • Not returning next.handle() observable
  • Using setTimeout instead of RxJS operators
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard