【发布时间】:2022-01-23 11:51:37
【问题描述】:
我有一个 Angular 应用程序,我想将 JSON 文件中的一堆变量挂载到 configService 中,Angular 应用程序从它自己的 Web 服务器获取,所以我可以将它作为 configMap 注入到容器中。
然后我希望这个服务和服务的配置成员属性在整个应用程序中都可以访问。
这是我现在所拥有的:
@Injectable({
providedIn: 'root'
})
export class ConfigService {
configUrl = '/config/cfg.json';
public config: Config | undefined;
constructor(private httpClient: HttpClient) {
}
getConfig(): Observable<Config> {
return this.httpClient.get<Config>(window.location.origin + this.configUrl)
.pipe(
catchError(this.handleError<Config>("getConfig", this.config = { apiBaseUrl: "", adminLoginUrl: "", clientLoginUrl: "" }))
)
}
getConfigObject() : Config | undefined{
if (this.config?.apiBaseUrl == undefined) {
this.getConfig().subscribe((data: Config) => this.config = {
apiBaseUrl: data.apiBaseUrl,
adminLoginUrl: data.adminLoginUrl,
clientLoginUrl: data.clientLoginUrl
})
}
return this.config;
}
//error handling omitted
}
在 getConfig() 方法上调用 subscribe 时,我最终得到了数据,但我不能使用它立即在该 apiBaseUrl 上调用一个函数,然后它是“未定义的”。 当我尝试调用 getConfigObject() 时,它不会返回对象,至少当时不会。
我想要做的是在调用我的后端 api 时使用这个 config.apiBaseUrl。 所以我可以在另一个服务/组件/模块中做到这一点:
@Injectable({
providedIn: 'root'
})
export class InvoiceService {
config: Config | undefined;
invoices: InvoiceItem[] | undefined;
confSub!: Subscription;
invSub!: Subscription;
//Idea 1, set the local config object in the constructor, does not work:
constructor(private configSvc: ConfigService, private httpClient: HttpClient) {
this.config = this.configSvc.getConfigObject()
}
getInvoices(): Observable<InvoiceItem[]> {
this.config = this.configSvc.config
console.log(this.config?.apiBaseUrl + "api/invoices");
//This above log results in just "api/invoices" in the console so the apiBaseUrl isn't loaded yet.
return this.httpClient.get<InvoiceItem[]>(this.config?.apiBaseUrl + "api/invoices")
.pipe(
catchError(this.handleError("getInvoices", this.invoices = []))
);
}
//idea 2: Get the configObject in the ngOnInit() (which I have, maybe wrongfully, added to a service) by calling the method that returns an observable.
ngOnInit(): void {
this.confSub = this.configSvc.getConfig()
.subscribe({
next: (data: Config) => this.config = data,
error: (err: Error) => console.log("Could not get config, " + err)
});
}
我昨天通过嵌套调用 configSvc.getConfig() 和 invoiceService.getInvoices() 不知何故让它工作了,但这导致发票端点发送垃圾邮件,这不是我期望使用的解决方案。
根据角度文档,可注入服务应该是单例,这让我期望调用 this.getConfig() 的 ngOnInit() 方法会用值填充实例变量“config”,然后这个实例将是可通过将其作为private configSvc: ConfigService 注入构造函数然后调用this.configSvc.config.apiBaseUrl 来访问和使用,但这也不起作用,它返回未定义。
我正在使用最新的稳定 Angular 版本。
我错过了什么?
编辑: 我知道里面:
this.confSub = this.configSvc.getConfig()
.subscribe({
next: (data: Config) => {
//HERE
this.config = data,
error: (err: Error) => console.log("Could not get config, " + err)
});
配置数据是可访问的,理论上我可以调用后端来获取发票,但我不能将其作为可观察的 getInvoices 函数返回。 这不起作用:
return this.configSvc.getConfig()
.subscribe({
next: (data: Config) => {
this.config = data;
return this.httpClient.get<Config>(window.location.origin + this.configUrl)
.pipe(
catchError(this.handleError<Config>("getConfig", this.config = { apiBaseUrl: "", adminLoginUrl: "", clientLoginUrl: "" }))
)
},
error: (err: Error) => console.log("Could not get config, " + err)
});
因为它会返回 config observable 而不是 InvoiceItem[] observable。 我将在多个地方需要后端 api url,所以我只想能够注入它并像这样使用它:
constructor(private httpClient: HttpClient, private configSvc: ConfigService) {}
...
return this.httpClient.get<something>(this.configSvc.config?.apiBaseUrl + "/some/endpoint")
就像一个在启动时挂载并在整个生命周期中保持活动和可访问的单例对象。 每次我想从后端端点获取东西时嵌套调用 configService 似乎是不必要的,或者我不太明白这是如何工作的。
【问题讨论】:
-
@Batajus 谢谢。我知道在订阅内部(在 getConfig 上)我可以访问 apiBaseUrl 但我不知道如何从订阅回调内部返回 Observable
。请参阅上面的编辑。 -
我还认为您可能想使用 BehviorSubject 而不是仅使用主题 - stackoverflow.com/questions/43348463/…
标签: angular kubernetes