如何在 Angular 中的提供程序配置期间从 useFactory 函数进行 HTTP 调用?
How to make an HTTP call from useFactory function during provider configuration in Angular?
我有下一个提供商配置
{
provide: APP_INITIALIZER,
useFactory: initializeKeycloak,
multi: true,
deps: [KeycloakService],
},
如何从 useFactory 函数 (initializeKeycloak) 进行 HTTP 调用?
function initializeKeycloak(keycloak: KeycloakService) {
return () =>
keycloak.init({
config: {
url: environment.keycloak.url,
realm: environment.keycloak.realm,
clientId: environment.keycloak.clientId
}
});
}
我想从资产文件夹中获取这个值
environment.keycloak.url
这里有两件事你需要知道:
- 在您的
asyncFactory
函数中,您可以 return 指示初始化何时完成的承诺。
- 您可以将
HttpClient
添加到 APP_INITIALIZER
的依赖项中。请注意,您必须将 HttpClientModule
添加到 AppModule
的导入中,以便它可用于注入。
RxJS 6 的工作示例:
const initializeKeycloak = (
keycloakService: KeycloakService,
httpClient: HttpClient // The httpClient is available here because you added it to the deps of the APP_INITIALIZER
) => {
return () =>
httpClient
.get(url)
.pipe(
tap((environment: any) => {
keycloakService.init({
config: {
url: environment.keycloak.url,
realm: environment.keycloak.realm,
clientId: environment.keycloak.clientId
}
});
})
)
.toPromise(); // Return the promise to indicate the initialization is done.
};
@NgModule({
imports: [BrowserModule, FormsModule, HttpClientModule],
declarations: [AppComponent, HelloComponent],
bootstrap: [AppComponent],
providers: [
{
provide: APP_INITIALIZER,
useFactory: initializeKeycloak,
multi: true,
deps: [KeycloakService, HttpClient] // Add the HttpClient here.
},
KeycloakService
]
})
export class AppModule {}
RxJS 7+ 的工作示例(toPromise 将被弃用,您必须使用 lastValueFrom):
import { lastValueFrom } from "rxjs";
...
const initializeKeycloak = (
keycloakService: KeycloakService,
httpClient: HttpClient
) => {
return () => {
const request$ = httpClient.get(url).pipe(
tap((environment: any) => {
keycloakService.init({
config: {
url: environment.keycloak.url,
realm: environment.keycloak.realm,
clientId: environment.keycloak.clientId
}
});
})
);
return lastValueFrom(request$);
};
};
旁注:
虽然可以在启动时检索环境信息,但缺点是如果请求失败,应用根本不会加载。
在这里添加一个 retry mechanism.
可能是值得的
还有一些方法可以在构建时注入环境变量,我在 this answer 中提供了有关该主题的信息。
我有下一个提供商配置
{
provide: APP_INITIALIZER,
useFactory: initializeKeycloak,
multi: true,
deps: [KeycloakService],
},
如何从 useFactory 函数 (initializeKeycloak) 进行 HTTP 调用?
function initializeKeycloak(keycloak: KeycloakService) {
return () =>
keycloak.init({
config: {
url: environment.keycloak.url,
realm: environment.keycloak.realm,
clientId: environment.keycloak.clientId
}
});
}
我想从资产文件夹中获取这个值
environment.keycloak.url
这里有两件事你需要知道:
- 在您的
asyncFactory
函数中,您可以 return 指示初始化何时完成的承诺。 - 您可以将
HttpClient
添加到APP_INITIALIZER
的依赖项中。请注意,您必须将HttpClientModule
添加到AppModule
的导入中,以便它可用于注入。
RxJS 6 的工作示例:
const initializeKeycloak = (
keycloakService: KeycloakService,
httpClient: HttpClient // The httpClient is available here because you added it to the deps of the APP_INITIALIZER
) => {
return () =>
httpClient
.get(url)
.pipe(
tap((environment: any) => {
keycloakService.init({
config: {
url: environment.keycloak.url,
realm: environment.keycloak.realm,
clientId: environment.keycloak.clientId
}
});
})
)
.toPromise(); // Return the promise to indicate the initialization is done.
};
@NgModule({
imports: [BrowserModule, FormsModule, HttpClientModule],
declarations: [AppComponent, HelloComponent],
bootstrap: [AppComponent],
providers: [
{
provide: APP_INITIALIZER,
useFactory: initializeKeycloak,
multi: true,
deps: [KeycloakService, HttpClient] // Add the HttpClient here.
},
KeycloakService
]
})
export class AppModule {}
RxJS 7+ 的工作示例(toPromise 将被弃用,您必须使用 lastValueFrom):
import { lastValueFrom } from "rxjs";
...
const initializeKeycloak = (
keycloakService: KeycloakService,
httpClient: HttpClient
) => {
return () => {
const request$ = httpClient.get(url).pipe(
tap((environment: any) => {
keycloakService.init({
config: {
url: environment.keycloak.url,
realm: environment.keycloak.realm,
clientId: environment.keycloak.clientId
}
});
})
);
return lastValueFrom(request$);
};
};
旁注:
虽然可以在启动时检索环境信息,但缺点是如果请求失败,应用根本不会加载。 在这里添加一个 retry mechanism.
可能是值得的还有一些方法可以在构建时注入环境变量,我在 this answer 中提供了有关该主题的信息。