首页 > 解决方案 > 在 Angular 组件的其余部分之前完全加载订阅

问题描述

我需要加载一个返回公共 IP 的公共 api,以便将不同的值传递给我的服务的 http post url。但在加载其余代码之前,我需要 api 响应。我来给你展示。

_RepService.service.ts 文件:(相关部分)

getPublicIP(): Observable<string> {
    return this._http.get<string>('https://api.ipify.org?format=json');
  }

 guardarParte(parte: NotaReparacion): Observable<JwtResponseI>{
    return this._http.post<JwtResponseI>(`${this.SERVERIP}/rep/gp`,
    parte).pipe(tap(
      (res:JwtResponseI)=>{
        if(res){console.log(res);};
        },
        error =>{console.log(error);}
    ));
  }

在组件的ngOnInit 中,我有:

this._RepService.getPublicIP().subscribe(
      (response) => {
        var ip = JSON.stringify(response['ip']);
        ip = ip.replace(/"/g,""); //regex
        console.log(ip);
        if (ip =="x.x.x.x") {
          this._RepService.SERVERIP = "http://y.y.y.y:1000";
        }else{
          this._RepService.SERVERIP = "http://x.x.x.x:1000";
        }
      }
    );

我尝试的是首先在 init 上加载 getPublicIP。所以 api 返回我的公共 IP,根据这个,不同的 IP 将用于访问数据(这是因为我需要在本地和从 Internet 访问数据)。问题是响应比代码加载慢,所以 _RepService.SERVERIP 为空,没有加载数据。如果我在 settimeout 中使用 console.log,我可以看到它正确加载。

我目前对此感到困惑,我什至不知道如何最好地解决这个问题。我应该在 app.component 中而不是在不同的组件中调用 api 吗?如何确保 api 在加载组件之前解析数据?还有其他想法可以正确解决此问题吗?

标签: angular

解决方案


我会避免在组件级别解析服务特定属性,而是做这样的事情。

@Injectable({
  providedIn: "root"
})
export class RepService {
  public get publicIP(): Promise<string> {
    return (async () => {
      if (!this._publicIP) {
        this._publicIP = await this.fetchPublicIP();
      }

      return this._publicIP;
    })();
  }

  private _publicIP: string | null = null;

  constructor(private _http: HttpClient) {}

  public guardarParte(parte: any): Observable<any> {
    return from(this.publicIP).pipe(
        switchMap(ip => this._http.post<any>(`${ip}/rep/gp`, parte))
    );
  }

  private async fetchPublicIP(): Promise<string> {
    return this._http
      .get<any>("https://api.ipify.org?format=json")
      .toPromise()
      .then(res => `http://${res.ip}`);
  }
}

采用这种方法,您可以在任何需要的地方使用guardarParte(...),如果需要,可以在后台完成获取publicIP。


推荐阅读