在Angular组件的其余部分之前完全加载订阅

时间:2020-11-12 11:16:46

标签: 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使用另一个IP来访问数据(这是因为我需要在本地和从Internet访问数据)。问题是响应速度比代码加载慢,因此_RepService.SERVERIP为空并且未加载数据。如果我在settimeout中使用console.log,我可以看到它已正确加载。

此刻我被阻止了,我什至不知道如何最好地解决问题。我应该在app.component中而不是在其他组件中调用api吗?如何确保在加载组件之前api能够解析数据?还有其他想法可以正确解决此问题吗?

1 个答案:

答案 0 :(得分:0)

我会避免在组件级别解析服务特定的属性,而应该执行类似的操作。

@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。