#angular #angular-providers #injection-tokens
Вопрос:
Мне нужно получить конфигурацию с помощью фабрики, которая будет разрешена во время ИНИЦИАЛИЗАЦИИ приложения (с помощью поставщика APP_INITIALIZER).
export function loadConfig(): () => Promise<Config> {
// return promised config
}
Это обеспечивается с помощью AppModule:
providers: [{
provide: APP_INITIALIZER,
useFactory: loadConfig,
deps: [HttpClient, ConfigService],
multi: true
}]
Затем мне нужно использовать эти данные конфигурации для ввода чего-либо внутри другого InjectionToken, но если я предоставлю конкретный injectiontoken, используя конфигурацию, предоставленную во время инициализации приложения, этот процесс выполняется до выполнения APP_INITIALIZER.
export const FORMATS = new InjectionToken<Formats>("formats")
export assignFormat(configService: ConfigService) {
return configService.getFormats(); // Needs to execute after APP_INITIALIZER, not before
}
providers: [{
provide: APP_INITIALIZER,
useFactory: loadConfig,
deps: [HttpClient, ConfigService],
multi: true
}, {
provide: FORMATS,
useFactory: assignFormat,
deps: [ConfigService]
}]
@Injectable({ providedIn: "root" })
export class ConfigService {
constructor() {}
getFormats() {}
}
Как я могу предоставить токен для инъекции после инициализации приложения?
Ответ №1:
То, что у вас здесь есть, должно действительно работать, если ваша loadConfig
фабрика возвращает функцию вместо фактического обещания:
const loadConfig = (configService: ConfigService) => {
return () =>
new Promise<void>((resolve, reject) => {
// I added the timeout to simulate a delay
setTimeout(() => {
// you might be using a http call to get the config from the server instead.
// Make sure you keep the config that you fetched in the service;
// this way you can inject the service in the next factory function
// and have the config available
configService.config = {
formats: 'formats',
};
resolve();
}, 1000);
});
};
Предоставление APP_INITIALIZER
выглядит точно так же, как в вашем коде:
{
provide: APP_INITIALIZER,
useFactory: loadConfig,
deps: [ConfigService],
multi: true,
},
Когда вы настраиваете следующий токен внедрения, у вас должна быть доступная конфигурация для использования
{
provide: FORMATS,
useFactory: (configService: ConfigService) => {
// getFormats method must not be async, it needs to return the actual
// formats that were fetched during the app initialization phase
return configService.getFormats();
},
deps: [ConfigService],
},
Единственные асинхронные фабрики, которые разрешены в Angular, — это те, которые вы используете с APP_INITIALIZER
токеном внедрения, но имейте в виду, что из них вам нужно возвращать функцию вместо фактического значения.
Комментарии:
1. Я отредактировал файл loadConfig, возвращающий функцию, которая возвращает обещание<Config>. Пробовал, как вы упомянули, но не работает.
2. Я попробовал решение, которое я опубликовал, и когда я
FORMATS
вводлю маркер инъекции в компонент, я получаю ожидаемое значение"formats"
.3. Решено, конфигурация не была задана в конкретном вызове, который я вызывал, у меня было три загрузки конфигурации (одна из статического файла, другие из сред), затем мне нужно было загрузить из файла не переменные env, так как они были загружены в APP_INITIALIZER, а другие из более позднего вызова. Ваш код работает нормально.
4. Хороший улов, я рад, что вы разобрались с этим :).