NestJS Circular dependency Explained In Hindi


NestJS में Circular Dependency एक ऐसा issue है जो तब होता है जब दो या दो से ज़्यादा modules या providers एक दुसरे पर directly या indirectly depend करते हैं, और यह loop create करते हैं जिससे application crash या unexpected behavior हो सकता है।

Circular dependencies को handle करना एक important aspect है जब आप scalable और maintainable applications build कर रहे होते हैं।

इस topic में हम समझेंगे कि Circular Dependency क्या होती है, यह कब होती है, कैसे इससे detect और fix किया जाता है, और कैसे हम NestJS में इस issue को avoid कर सकते हैं।

What is Circular Dependency In NestJs

Circular Dependency तब होती है जब दो या दो से ज़्यादा modules या services एक दुसरे पर indirectly या directly depend करते हैं, जिससे एक loop create हो जाता है।

इसका मतलब, अगर Service A को Service B का instance चाहिए और Service B को Service A का, तो यह circular dependency है।

For example

  • Service A → Depends on Service B

  • Service B → Depends on Service A

जब NestJS dependency injection system यह detect करता है, तो यह circular reference के कारण error throw करता है, या फिर application crash हो सकता है।

NestJs Circular Dependency Example

चलिए एक simple example देखते हैं जिसमे circular dependency introduce होती है।

Step 1 : Service A

File : src/services/service-a.ts

import { Injectable } from '@nestjs/common'; import { ServiceB } from './service-b'; @Injectable() export class ServiceA { constructor(private serviceB: ServiceB) {} getServiceBMessage() { return this.serviceB.getMessage(); } }
Step 2 : Service B

File : src/services/service-b.ts

import { Injectable } from '@nestjs/common'; import { ServiceA } from './service-a'; @Injectable() export class ServiceB { constructor(private serviceA: ServiceA) {} getMessage() { return 'Hello from Service B!'; } }

यहां -

  • Service A को Service B का instance चाहिए, और

  • Service B को Service A का instance चाहिए।

यह circular dependency है, क्योंकि दोनो services एक दुसरे पर depend कर रही हैं। यह NestJS के Dependency Injection (DI) system को confuse कर सकती है और runtime errors या crashes हो सकते हैं।

Detect Circular Dependency In NestJs

NestJS circular dependencies को detect करता है और error messages throw करता है जिसमे आपको पता चल जाता है कि कौनसे providers circular dependency में फसे हुए हैं।

जब NestJS circular dependency detect करता है, तब आपको console में कुछ इस तरह का error message मिल सकता है -

[ExceptionHandler] Circular dependency found: "ServiceA" <- "ServiceB"

इससे आपको पता चल जाता है कि circular dependency का loop कहा पर है।

Fix Circular Dependencies In NestJs

1. Using forwardRef()

Circular dependencies को fix करने का एक effective तरीका है forwardRef() function का use. forwardRef() NestJS को बताता है कि जब circular dependency introduce होती है, तो injection को defer कर दिया जाये जब तक दोनो services inject हो सकें।

forwardRef() का use करते hue आप dependencies को handle कर सकते हैं बिना application को crash किये।

Step 1 : use of forwardRef() In Service A

File : src/services/service-a.ts

import { Injectable, forwardRef, Inject } from '@nestjs/common'; import { ServiceB } from './service-b'; @Injectable() export class ServiceA { constructor(@Inject(forwardRef(() => ServiceB)) private serviceB: ServiceB) {} getServiceBMessage() { return this.serviceB.getMessage(); } }
Step 2 : Use of forwardRef() In Service B

File : src/services/service-b.ts

import { Injectable, forwardRef, Inject } from '@nestjs/common'; import { ServiceA } from './service-a'; @Injectable() export class ServiceB { constructor(@Inject(forwardRef(() => ServiceA)) private serviceA: ServiceA) {} getMessage() { return 'Hello from Service B!'; } }

यहां @Inject(forwardRef(() => ServiceA)) और @Inject(forwardRef(() => ServiceB)) का use किया गया है, जो circular dependencies को defer करता है जब तक services properly inject हो सकें।

2. Using Interfaces

आप interfaces का use करके circular dependency को break कर सकते हैं। Interfaces का use करने से आप dependency injection को loosely couple कर सकते हैं।

3. Using Event Emitters

Circular dependency को handle करने का एक और तरीका Event Emitters का use करना है।

इस approach में, एक service दूसरी service का directly reference नहीं लेती, बल्कि events के through data pass करती है।

NestJs Example of solving circular dependency

चलिए एक practical example implement करते हैं जिसमे forwardRef() का use करके circular dependency को fix करते हैं।

Step 1 : Service A (CD Fixed)

File : src/services/service-a.ts

import { Injectable, Inject, forwardRef } from '@nestjs/common'; import { ServiceB } from './service-b'; @Injectable() export class ServiceA { constructor(@Inject(forwardRef(() => ServiceB)) private serviceB: ServiceB) {} getServiceBMessage() { return this.serviceB.getMessage(); } getMessage() { return 'Hello from Service A!'; } }
Step 2 : Service B (CD Fixed)

File : src/services/service-b.ts

import { Injectable, Inject, forwardRef } from '@nestjs/common'; import { ServiceA } from './service-a'; @Injectable() export class ServiceB { constructor(@Inject(forwardRef(() => ServiceA)) private serviceA: ServiceA) {} getMessage() { return 'Hello from Service B!'; } }
Step 3 : Register Services in Module

File : src/app.module.ts

import { Module, forwardRef } from '@nestjs/common'; import { ServiceA } from './services/service-a'; import { ServiceB } from './services/service-b'; @Module({ providers: [ forwardRef(() => ServiceA), forwardRef(() => ServiceB), ], exports: [ServiceA, ServiceB], }) export class AppModule {}

यहां -

  • forwardRef() का use services को module में register करने के लिए किया है।

  • Circular dependency को properly handle किया गया है without causing runtime errors.

Step 4 : Use Services In Controller

File : src/app.controller.ts

import { Controller, Get } from '@nestjs/common'; import { ServiceA } from './services/service-a'; import { ServiceB } from './services/service-b'; @Controller() export class AppController { constructor( private serviceA: ServiceA, private serviceB: ServiceB ) {} @Get('service-a') getServiceAMessage() { return this.serviceA.getMessage(); } @Get('service-b') getServiceBMessage() { return this.serviceB.getMessage(); } }

यहां Service A और Service B को inject किया गया है और उनके methods को call किया गया है।

Best Practices To Avoid Circular Dependencies

  • Use forwardRef() Judiciously : forwardRef() का use तभी करें जब आपको circular dependency का issue हो। इसका overuse avoid करें, क्योंकि यह application के design को complex बना सकता है।

  • Refactor Services : Circular dependencies को avoid करने के लिए services को refactor करें। अगर दो services एक दुसरे पर heavily depend कर रही हैं, तो यह code design issue हो सकता है।

  • Use Interfaces : Interfaces का use करके services को loosely couple करें, इससे आप circular dependencies को break कर सकते हैं।

Conclusion

Circular Dependency एक common issue है जो large-scale NestJS applications में आ सकता है, लेकिन इससे handle करना जरूरी होता है ताकि application का design clean और maintainable रहे।

इस topic में हमने समझा कि circular dependencies क्या होती हैं, कैसे forwardRef() का use करके इहे resolve किया जा सकता है, और कैसे best practices का use करके circular dependencies को avoid किया जा सकता है।

Hey ! I'm Rahul founder of learnhindituts.com. Working in IT industry more than 4.5 years. I love to talk about programming as well as writing technical tutorials and blogs that can help to others .... keep learning :)

Get connected with me - LinkedIn Twitter Instagram Facebook