Инъекция против инъекций против пользовательских провайдеров - PullRequest
0 голосов
/ 17 апреля 2020

Мне трудно понять, когда что использовать. Я понимаю DI и делал это годами, но в Nest JS кажется, что в документах не хватает вещей, которые помогли бы мне понять, почему некоторые присвоенные свойства go отсутствуют в введенном элементе.

У нас есть регистратор, который вводится через собственного провайдера.

При просмотре документов они добавят @Inject в области конструктора, но если я внедряю через собственного провайдера, зачем использовать @Inject?

Точно так же, зачем использовать @Injectable, если у нас есть пользовательские провайдеры, обрабатывающие все настройки впрыска для модуля?

В связи с этим возникает вопрос, что имя файла теряется среди других введенных сервисы, где иногда, когда регистратор запускается в одном сервисе, имя файла совпадает, в то время как в другом случае сервис отличается от другого, он сохраняет имя файла из имени ctor другого сервиса.

В любом случае, я не надену не понимаю, почему использовать один набор над другим.

Обновление: я обнаружил, что мы следуем за LifeCycle в некоторых Сервисах, но я обнаружил, что регистратор не сохраняется во время выполнения.

//custom-provider
export ClientProvider = {
   provide: Client,
   userFactory: (logger: Logger): Client => {
        return new Client(logger);
   },
   inject: [Logger.getToken()]
};

//client
export class Client{
    private readonly logger;
    constructor(logger:Logger){
        this.logger = logger;
        if (this.logger) this.logger.fileName = this.constructor.name;
    }
}

//logger
export class Logger {
    static getToken(): string { return 'the-token-key'; }
    private filename: string;

    constructor(filename: string){
        this.filename = filename;
    }
}

//cat-service
export class CatService implements OnModuleInit {
    private readonly logger;
    constructor(@Inject(Logger.getToken()) private logger:Logger){
        this.logger = logger;
    }

    onModuleInit() {
       if (this.logger) this.logger.fileName = this.constructor.name;
    }
}

1 Ответ

1 голос
/ 17 апреля 2020

Итак, на высоком уровне Nest, естественно, использует метаданные, отраженные из Typescript, чтобы знать, что и где связывать. Обычно эти метаданные представляют собой такие вещи, как имена классов, которые существуют во время выполнения, поэтому вы не можете использовать интерфейсы.

@Injectable() сообщает Nest, что он должен найти метаданные, предоставленные в конструкторе этого класса, и найти правильных поставщиков. Вот как Nest выполняет большую часть DI, как упоминалось ранее.

@Inject() говорит Nest: «Эй, я знаю, что это говорит о том, что это Logger класс, но на самом деле вводит провайдеру токен инъекции Я говорю вам ", что полезно для таких вещей, как использование определенных c экземпляров, скажем, класса Logger.

При использовании собственного провайдера, @Injectable() не требуется, если вы используете фабрику, так как вы показали, но это было бы, если бы вы использовали вместо этого класс, потому что фабрики возвращают экземпляр значения, которое будет предоставлено, тогда как с useClass вы возвращаете определение класса, которое Nest должен будет создать. 1013 * Единственная причина, по которой я мог видеть, что ваше имя файла перезаписано, заключается в том, что провайдеры имеют одноэлементную область видимости между модулями, но если один и тот же провайдер находится в массиве providers, то каждый раз это должен быть новый экземпляр, так что, возможно, что-то с этим действует немного шаткий

...