У меня есть приложение Angular, которое использует библиотеку. Я хочу настроить библиотеку с некоторыми значениями конфигурации, которые динамически загружаются приложением через HTTP-вызов (и поэтому недоступны во время компиляции).
Какой лучший подход для этого? Спасибо!
Я пробовал следующие методы, но у каждого из них есть существенные недостатки:
A. LibraryModuleA.forRoot (поставщик: поставщик)
Я создал метод forRoot для модуля в lib, который принимает аргумент провайдера, а затем использовал токен Injection, чтобы сделать конфигурацию инъекционной в библиотеке.
Недостатком этого подхода является то, что модуль, который хочет использовать библиотеку, должен знать много, чтобы заставить ее работать.
Модуль библиотеки:
@NgModule({
// omitted for brevity
})
export class LibraryModuleA{
static forRoot(provider: Provider): ModuleWithProviders {
return {
ngModule: LibraryModuleA,
providers: [provider]
};
}
}
Клиентский модуль, который использует библиотечный модуль:
@NgModule({
imports: [
LibraryModuleA.forRoot({
provide: LIBRARY_CONFIGURATION,
useFactory: (coreState: CoreState): LibraryConfiguration =>
new LibraryConfiguration(coreState.config1$.value, coreState.config2$.value),
deps: [CoreState]
})
],
// omitted for brevity
Как видите, клиентский модуль должен создать объект LibraryConfiguration
, и ему нужно внедрить его под токеном LIBRARY_CONFIGURATION
. Мне кажется, это слишком большая ответственность за клиента библиотеки.
B. LibraryModuleA.forRoot (config1: строка, config2: строка) и глобальный синглтон
Я создал глобальный синглтон, в котором храню значения конфигурации, и II создал метод forRoot для модуля в lib, который принимает конфигурацию в качестве параметра, а затем использует токен Injection, чтобы сделать конфигурацию инъекционной в библиотеке.
Недостатком этого является то, что у меня теперь есть глобальный синглтон, что никогда не было хорошей идеей и могло стать причиной будущих проблем.
Библиотечный модуль:
@NgModule({
// omitted for brevity
})
export class LibraryModuleA {
static forRoot(config1: string, config2: string): ModuleWithProviders {
return {
ngModule: LibraryModuleA ,
providers: [
{
provide: LIBRARY_CONFIGURATION,
useValue: new LibraryConfiguration(config1, config2)
}
]
};
}
Объект глобального состояния:
class GlobalState {
config1$: BehaviorSubject<string> = new BehaviorSubject<ApplicationSettings>('');
config2$: BehaviorSubject<string> = new BehaviorSubject<User>('');
}
const GLOBAL_STATE: GlobalState = new GlobalState ();
export default GLOBAL_STATE;
Клиентский модуль, который использует библиотечный модуль:
@NgModule({
imports: [
LibraryModuleA.forRoot(
GLOBAL_STATE.config1$.getValue(),
GLOBAL_STATE.config2$.getValue()
)
],
// omitted for brevity
})
C. LibraryConfigurationService
Я создал службу конфигурации библиотеки, которая доступна на корневом уровне, и затем я вызываю метод init для этой службы один раз после получения конфигурации из вызова http.
Недостатком этого подхода является то, что вы не должны забывать вызывать метод службы конфигурации, если хотите использовать библиотеку.