#nestjs
#nestjs
Вопрос:
Я пытаюсь инициализировать a ConfigurationService
с помощью onModuleInit
перехвата. Ссылаясь на страницу перехватов жизненного цикла NestJS, я ожидаю, что перехват будет вызван при создании модуля. Однако это не так. В принципе, у меня есть это:
ConfigurationService:
import { Injectable, OnModuleInit } from '@nestjs/common';
import { ApplicationConfiguration } from './interfaces/application-configuration.interface';
import { ServerConfiguration } from './interfaces/server-configuration.interface';
import * as path from 'path';
@Injectable()
export class ConfigurationService implements OnModuleInit {
private _configuration: ApplicationConfiguration;
public async getServerConfigurationAsync(): Promise<ServerConfiguration> {
await this.ensureConfigurationIsLoadedAsync();
return new Promise<ServerConfiguration>((resolve, reject) => {
const serverConfiguration = this._configuration.server;
if (!serverConfiguration) {
reject(new Error('Missing server configuration.'));
}
return resolve(serverConfiguration);
});
}
private async ensureConfigurationIsLoadedAsync(): Promise<void> {
if (!this._configuration) {
this._configuration = await this.fetchAppConfigurationAsync();
}
}
private fetchAppConfigurationAsync(): Promise<ApplicationConfiguration> {
const configDir = process.env.CONFIG_DIR;
let configurationPath: string;
if (configDir) {
configurationPath = path.resolve(`configuration/${configDir}/config.json`);
}
else {
configurationPath = path.resolve('configuration/config.json');
}
return new Promise<ApplicationConfiguration>((resolve, reject) => {
try {
const configuration = require(configurationPath);
const mappedConfig: ApplicationConfiguration = {
server: configuration.server
};
resolve(mappedConfig);
}
catch (error) {
console.log(`Can't fetch configuration at ${configurationPath}.`);
reject(error);
}
});
}
// public async onModuleInit(): Promise<void> {
// console.log('ConfigurationService onModuleInit called.');
// await this.ensureConfigurationIsLoadedAsync();
// }
public onModuleInit(): void {
console.log('ConfigurationService onModuleInit called.');
}
}
Конкретный асинхронный провайдер:
export const SERVER_CONFIGURATION_PROVIDER: Provider = {
provide: CONFIGURATION_TOKENS.SERVER_CONFIGURATION,
useFactory: async (configurationService: ConfigurationService): Promise<ServerConfiguration> => {
console.log('SERVER_CONFIGURATION_PROVIDER useFactory called.');
return await configurationService.getServerConfigurationAsync();
},
inject: [ConfigurationService]
}
Модуль конфигурации:
@Module({
providers: [
ConfigurationService,
SERVER_CONFIGURATION_PROVIDER
],
exports: [
SERVER_CONFIGURATION_PROVIDER
]
})
export class ConfigurationModule {
// public async onModuleInit(): Promise<void> {
// console.log('ConfigurationModule onModuleInit called.');
// }
public onModuleInit(): void {
console.log('ConfigurationModule onModuleInit called.');
}
}
И вот как я пытаюсь его использовать:
@Controller('app')
export class AppController {
private _serverConfig: ServerConfiguration;
constructor(@Inject(CONFIGURATION_TOKENS.SERVER_CONFIGURATION) serverConfig: ServerConfiguration) {
this._serverConfig = serverConfig;
}
@Get()
public async getResult(): Promise<any> {
return this._serverConfig;
}
}
Теперь дело в том, что я хочу отменить await this.ensureConfigurationIsLoadedAsync();
вызов в getServerConfigurationAsync()
методе и инициализировать конфигурацию через onModuleInit
перехват. Однако при запуске приложения перехват вызывается задолго до ConfigurationService
того, как он используется асинхронным провайдером. Я что-то упустил? Не следует ли вызывать перехват до того, как служба будет использована? В документации говорится:
Вызывается после разрешения зависимостей хост-модуля.
И
Для каждого модуля после инициализации модуля:
ожидание дочернего контроллера и методов onModuleInit() поставщика
метод ожидания модуля onModuleInit()
Тем не менее, я также нашел это в исходном коде:
nest/packages/core/nest-application.ts
public async init(): Promise<this> {
this.applyOptions();
await this.httpAdapter?.init();
const useBodyParser =
this.appOptions amp;amp; this.appOptions.bodyParser !== false;
useBodyParser amp;amp; this.registerParserMiddleware();
await this.registerModules();
await this.registerRouter();
await this.callInitHook();
await this.registerRouterHooks();
await this.callBootstrapHook();
this.isInitialized = true;
this.logger.log(MESSAGES.APPLICATION_READY);
return this;
}
Поэтому я не уверен, чего ожидать, и правильно ли я понимаю жизненный цикл. Вот мой журнал при запуске приложения:
Before app create
[Nest] 28132 - 10/05/2020, 4:12:38 PM [NestFactory] Starting Nest application...
SERVER_CONFIGURATION_PROVIDER useFactory called.
[Nest] 28132 - 10/05/2020, 4:12:38 PM [InstanceLoader] ConfigurationModule dependencies initialized 10ms
[Nest] 28132 - 10/05/2020, 4:12:38 PM [InstanceLoader] AppModule dependencies initialized 1ms
After app create
before listen
[Nest] 28132 - 10/05/2020, 4:12:38 PM [RoutesResolver] AppController {/api/app}: 5ms
[Nest] 28132 - 10/05/2020, 4:12:38 PM [RouterExplorer] Mapped {/api/app, GET} route 4ms
ConfigurationService onModuleInit called.
ConfigurationModule onModuleInit called.
[Nest] 28132 - 10/05/2020, 4:12:38 PM [NestApplication] Nest application successfully started 2ms
after listen
Listening at port 5000.
Комментарии:
1.
the hook gets called long after the ConfigurationService gets consumed by the async provider. Am I missing something? Shouldn't the hook be invoked before the service gets consumed?
Что вы подразумеваете под «потреблять»? Сначала происходит создание экземпляра и внедрение. Затем он выполняет обратный цикл и вызывает onModuleInit.