0
0
Lập trình
Admin Team
Admin Teamtechmely

Tìm Hiểu Circular Dependency trong NestJS và 3 Giải Pháp Hiệu Quả

Đăng vào 2 tuần trước

• 3 phút đọc

Tìm Hiểu Circular Dependency Trong NestJS

Circular Dependency (phụ thuộc vòng tròn) là một vấn đề thường gặp trong lập trình, đặc biệt là khi làm việc với NestJS. Đây là một khái niệm không chỉ quan trọng mà còn thường xuyên xuất hiện trong các cuộc phỏng vấn về NestJS. Trong bài viết này, chúng ta sẽ cùng nhau tìm hiểu về circular dependency và những cách giải quyết hiệu quả để xử lý vấn đề này.

Khái Niệm Circular Dependency Trong NestJS

Trong NestJS, circular dependency xảy ra khi hai hoặc nhiều module hoặc provider phụ thuộc vào nhau, tạo thành một vòng lặp. Điều này có thể dẫn đến các vấn đề nghiêm trọng như lỗi runtime hoặc hành vi không mong muốn, vì NestJS không thể giải quyết các phụ thuộc một cách chính xác.

Ví dụ:

  • Module A phụ thuộc vào Module B.
  • Module B lại phụ thuộc vào Module A.

Ví Dụ Thực Tế Về Circular Dependency

Dưới đây là một ví dụ đơn giản về circular dependency giữa hai service trong NestJS:

service-a.service.ts

typescript Copy
import { Injectable } from '@nestjs/common';
import { ServiceB } from './service-b.service';

@Injectable()
export class ServiceA {
  constructor(private readonly serviceB: ServiceB) {}

  getMessageFromB(): string {
    return this.serviceB.getMessage();
  }
}

service-b.service.ts

typescript Copy
import { Injectable } from '@nestjs/common';
import { ServiceA } from './service-a.service';

@Injectable()
export class ServiceB {
  constructor(private readonly serviceA: ServiceA) {}

  getMessage(): string {
    return `Hello from ServiceB. Called by: ${this.serviceA.getMessageFromB()}`;
  }
}

Như bạn thấy, cả ServiceAServiceB đều phụ thuộc lẫn nhau, gây ra vấn đề circular dependency.

Thông Báo Lỗi Thường Gặp

Khi chạy đoạn mã trên, NestJS sẽ trả về một lỗi tương tự như sau:
Error: A circular dependency has been detected (ServiceA -> ServiceB -> ServiceA).

Các Giải Pháp Để Giải Quyết Circular Dependency

1. Sử Dụng forwardRef

NestJS cung cấp hàm forwardRef để xử lý vấn đề circular dependency. Bạn có thể sử dụng forwardRef trong constructor để tránh lỗi.

Ví dụ:

service-a.service.ts

typescript Copy
import { Injectable, forwardRef, Inject } from '@nestjs/common';
import { ServiceB } from './service-b.service';

@Injectable()
export class ServiceA {
  constructor(@Inject(forwardRef(() => ServiceB)) private readonly serviceB: ServiceB) {}

  getMessageFromB(): string {
    return this.serviceB.getMessage();
  }
}

service-b.service.ts

typescript Copy
import { Injectable, forwardRef, Inject } from '@nestjs/common';
import { ServiceA } from './service-a.service';

@Injectable()
export class ServiceB {
  constructor(@Inject(forwardRef(() => ServiceA)) private readonly serviceA: ServiceA) {}

  getMessage(): string {
    return `Hello from ServiceB. Called by: ${this.serviceA.getMessageFromB()}`;
  }
}

2. Tái Cấu Trúc Code Để Tránh Circular Dependency

Một phương pháp khác là tái cấu trúc code để tránh việc các service phụ thuộc trực tiếp vào nhau. Bạn có thể tạo một service trung gian (Mediator) để điều phối các tương tác.

Tạo mediator.service.ts

typescript Copy
import { Injectable } from '@nestjs/common';

@Injectable()
export class MediatorService {
  getSharedMessage(): string {
    return 'Shared Message';
  }
}

Cập Nhật service-a.service.ts

typescript Copy
import { Injectable } from '@nestjs/common';
import { MediatorService } from './mediator.service';

@Injectable()
export class ServiceA {
  constructor(private readonly mediatorService: MediatorService) {}

  getMessageFromMediator(): string {
    return this.mediatorService.getSharedMessage();
  }
}

Cập Nhật service-b.service.ts

typescript Copy
import { Injectable } from '@nestjs/common';
import { MediatorService } from './mediator.service';

@Injectable()
export class ServiceB {
  constructor(private readonly mediatorService: MediatorService) {}

  getMessageFromMediator(): string {
    return this.mediatorService.getSharedMessage();
  }
}

3. Tổ Chức Lại Cấu Trúc Module

Nếu circular dependency phát sinh từ việc các module import lẫn nhau, hãy cân nhắc tổ chức lại cấu trúc module. Đưa logic dùng chung vào một module riêng để cả hai module có thể cùng phụ thuộc mà không gặp vấn đề về circular dependency.

Tóm Tắt

  • Sử dụng forwardRef là một cách xử lý nhanh chóng nhưng nên cẩn thận, không nên lạm dụng để tránh làm phức tạp thiết kế ứng dụng.
  • Cách tốt nhất là tái cấu trúc code để tránh hoàn toàn circular dependency.
  • Xem xét sử dụng mediator hoặc tổ chức lại module để quản lý phụ thuộc một cách rõ ràng hơn.

Đọc Thêm

Để tìm hiểu thêm về circular dependency và cách giải quyết, bạn có thể tham khảo tài liệu chính thức của NestJS tại đây. Ngoài ra, bạn có thể xem đoạn code mẫu của mình về cách giải quyết circular dependency trên GitHub. Cùng tham khảo thêm các khái niệm cơ bản trong series NestJS Cơ Bản và bài viết gốc của mình tại đây.
source: viblo

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào