Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
322 views
in Technique[技术] by (71.8m points)

node.js - How does InjectRepository work internally in NestJS?

In nestjs, I understand that

imports: [
    TypeOrmModule.forFeature([TaskRepository]),
],

creates some kind of provider token so then I can inject the repository in my service (in same module) with this token.

What I don't understand is how @InjectRepository() works internally, for example:

constructor(
    @InjectRepository(TaskRepository)
    private taskRepository: TaskRepository,
  ) {}

How is InjectRepository custom decorator (which should have been created with createParamDecorator) able to inject a provider registered in a module? I researched and found out that createParamDecorator doesn't have ability to use DI. If createParamDecorator just creates a new TaskRepository instance and returns it, then why do I need to import TypeOrmModule.forFeature in module? Can someone explain how this works internally? Thanks!

question from:https://stackoverflow.com/questions/65938257/how-does-injectrepository-work-internally-in-nestjs

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You're on the right track, but @InjectRespoitory() and createParamDecorator() are generally two different decorator types. Yes they both work on parameters, but they generally have different use cases.

createParamDecorator works on controller, resolver, and gateway route handlers, so that Nest can know what part of the req, context, or payload object (or whatever other part of the ExecutionContext you want to get) should be put into the route handler's parameter position. The code behind that is a little complex, but I can point you to it if you get really curious.

@InjectRepository() on the other hand is an extension of @Inject() that takes the currently passed entity/repository and uses some logic to create a new injection token. Generally, this logic is <EntityName>Repository sometimes with a connection added to it. This token matches up with the created token from TypeormModule.forFeature() for the same entity. (Side note: if the entity passed is a repository, the token is just <EntityName> with the optional connection if it is not the default one).

You can try this out but getting rid of @InjectRepository() and instead using @Inject() just for testing purposes, but I wouldn't suggest that in a production server instance. Too many chances it will go wrong.

The really important thing to make note of here is that @InjectRepository() doesn't actually inject anything. It just sets up the metadata for Nest to read and match to a custom provider. TypeormModule.forFeature() is actually what's doing the heavy lifting here, creating a custom provider with a matching injection token and providing the right value for the provider.

By the way, @InjectRepository() and TypeormModule.forFeature() have to work together because Typescript cannot reflect generics properly. Normally with Nest we can use class names as injection tokens, but something like Repository<TaskEntity> just comes back as Repository so Nest wouldn't know which repository to inject. By using the @InjectRepository() decorator we are able to set the injection token metadata and override the reflected class value.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...