RxJS的角度:在调用方法之前,请确保使用http.get的服务的构造函数已完成

时间:2018-08-27 15:43:29

标签: angular rxjs angular6

在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;会引发错误。

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

3 个答案:

答案 0 :(得分:2)

您应该始终使用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调用。为此,使用RxJS shareReplay运算符也至关重要。

用法:

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

答案 1 :(得分:0)

您无法执行此操作,这与RxJS的概念背道而驰。

在我看来,这更多是个概念问题,您可以使用不同的解决方案来解决此问题:

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

  2. 处理configKeysnullgetAuthenticationBaseRoute的情况,并使其返回undefined。但是,您还必须在呼叫getAuthenticationBaseRoute的情况下进行处理。

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

答案 2 :(得分:0)

好吧,我找到了一种方法: 使用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;
    }
}