DEV Community

Cover image for Circular dependency in Nest JS
Adeleke Ayobami
Adeleke Ayobami

Posted on

Circular dependency in Nest JS

I recently came about this Error while running a nest js application

Nest Error

Firstly, it is important to know that what brought about circular dependency is Dependency Injection
So to have an understanding of circular dependency, one needs to understand dependency injection

Dependency injection is the process of supplying a resource that a given piece of code requires. The required resource, which is often a component of the application itself is called a dependency.

Basically, instead of having a class declare objects that it depends on, these objects should be fed to your class.

This essentially means our code is more decoupled and testable.

Even though dependency injection makes code easier to write and test, we occasionally encounter some issues one of which is circular dependency

let's picture this;
Say we have two services; A and B.

If service A, depends on a resource in service B and service B depends on a resource in A to run, then we have a circular dependency.

To compile A, you must first Compile B, but you can't do that because A requires B to be compiled.

circular dependencies can arise in Nest between modules and between providers.

As much as possible, circular dependencies should be avoided, but in cases where you can't, nest provides a workaround

A forward reference allows Nest to reference classes that aren't yet defined using the forwardRef() utility function. This can be imported from the @nestjs/common package

let's look at some code, shall we?

user.js

@injectable()
export class UserService {
constructor(
@inject(forwardRef(()=> BlogService))
private blogService: BlogService

Enter fullscreen mode Exit fullscreen mode

blog.js

@injectable()
export class BlogService {
constructor(
@inject(forwardRef(()=> UserService))
private userService: UserService

Enter fullscreen mode Exit fullscreen mode

from the above, we can see that both User service and Blog service need each other hence a forwardRef()

This can also be done on the module level on both sides of the association as well

user.module.js


@Module({
imports: [forwardRef(() => BlogModule)]})
export class UserModule {}

Enter fullscreen mode Exit fullscreen mode

**

Removing the dependency

**
One major problem with circular dependency is that it creates tight couplings which the famous SOLID principles preach against.

In the above example, Circular Dependency can be removed by extracting the common features of both services into a new service that would simply depend on the services.

In our case, a third service called profile service is introduced to hold the necessary information relevant to both the user and blog service. This eventually breaks the cycle

With circular dependency
UserService -> BlogService
BlogService -> UserService

Without circular dependency
UserService -> ProfileService
BlogService -> ProfileService

I would love to know if you've encountered circular dependency in nest js and how you resolved it 😄.
Kindly share your thoughts in the comments below!

Thanks

Top comments (2)

Collapse
 
louiecodes profile image
L O U I S • Edited

I'm still learning NestJS while making a real project and I haven't stumbled upon circular dependecy yet, but it's good to be aware of these things that could happen and how to resolve them.
It would be great if you could highlight the code examples you provided, other than that, good article!

Collapse
 
matbami profile image
Adeleke Ayobami

Thanks @louiecodes. I will do well to provide examples in detail when I can. Good luck on your learning journey👍