Angular with RxJS:确保在调用方法之前完成使用 http.get 的服务构造函数



在 Angular 6 中,我有一个ConfigService,要求构造函数完成才能正常工作:

import { HttpClient, HttpHeaders, HttpErrorResponse } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Observable, Subscribable, Subscription } from "rxjs";
@Injectable()
export class ConfigService {
public configKeys: any;
constructor(private http: HttpClient) {
this.http.get('config/config.json').subscribe(
data => {
this.configKeys = data;
},
(err: HttpErrorResponse) => {
console.log (err.message);
}
);
}
getDocBaseRoute() :string{
return this.configKeys.docBaseRoute;
}
getAuthenticationBaseRoute() :  Subscription {
return this.configKeys.authenticationBaseRoute;
}
}

当我尝试调用服务的方法时触发了一个问题:

this.baseUrl = this.configservice.getAuthenticationBaseRoute();

实际上,此时configKeys尚未定义,因此return this.configKeys.authenticationBaseRoute;抛出错误。

那么,您能否帮助我知道如何在调用服务方法之前确定构造函数已完成?

您应该始终使用 RxJS 才能正常工作。

import { HttpClient, HttpErrorResponse } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Observable } from "rxjs";
import { shareReplay, map } from 'rxjs/operators';
@Injectable()
export class ConfigService {
private configuration: Observable<any>;
constructor(private http: HttpClient) { }
getDocBaseRoute(): Observable<string> {
return this.getConfiguration().pipe(map(data => data.docBaseRoute));
}
getAuthenticationBaseRoute(): Observable<any> {
return this.getConfiguration().pipe(map(data => data.authenticationBaseRoute));
}
private getConfiguration(): Observable<any> {
if(!this.configuration) {
this.configuration = this.http.get('config/config.json').pipe(
catchError((error: HttpErrorResponse) => console.log(err.message)),
shareReplay()
);
}
return this.configuration;
}
}

请注意,我存储Observable,而不是将结果存储在属性中。如果不执行此操作并多次调用getConfiguration(),则由于计时原因,可能会发生多个 HTTP 调用。为此,使用 RxJSshareReplay运算符也至关重要。

用法:

this.configservice.getAuthenticationBaseRoute().subscribe(baseRoute => this.baseUrl = baseRoute);

你没有办法做到这一点,那将违背RxJS的概念。

在我看来,这更像是一个概念问题,你可以有不同的解决方案来处理这个问题:

  1. 定义configKeys的默认值,以便getAuthenticationBaseRoute永远不会失败。

  2. 处理configKeysnullgetAuthenticationBaseRoute内的情况,并让它返回undefined。但是您还必须处理这种情况,其中您调用getAuthenticationBaseRoute.

  3. 使组件/服务/调用getAuthenticationBaseRoute的任何内容在ConfigService中定义之前configKeys都无法调用它。

好的,我找到了一种方法: 使用 toPromise(( 将可观察转换为承诺

import { HttpClient, HttpHeaders, HttpErrorResponse } from "@angular/common/http";
import { Injectable } from "@angular/core";
@Injectable()
export class ConfigService {
public configKeys: any;
constructor(private http: HttpClient) {
}
async getGestionDocumentBaseRoute(): Promise<string> {
await this.initialize();
return this.configKeys.gestionDocumentBaseRoute;
}
private async initialize(): Promise<boolean> {
if (!this.configKeys) {
await this.http.get('config/config.json').toPromise()
.then(
data => {
this.configKeys = data;
}
)
.catch(
(err: HttpErrorResponse) => {
console.log(err.message);
return false;
}
);
}
return true;
}
async getAuthenticationBaseRoute(): Promise<string> {
await this.initialize();
return this.configKeys.authenticationBaseRoute;
}
}

最新更新