繁体   English   中英

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

[英]Angular with RxJS: be sure service's constructor using http.get is finished before call method

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

因此,您可以帮助我知道如何确定在调用服务的方法之前构造函数已经完成吗?

您应该始终使用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);

您无法做到这一点,这与RxJS的概念背道而驰。

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

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

  2. 处理getAuthenticationBaseRoute内部configKeysnull并返回undefined 但是,您还必须在调用getAuthenticationBaseRoute情况下处理这种情况。

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

好的,我找到了一种方法:使用toPromise()将可观察的对象转换为一个Promise

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;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM