我需要加载一个返回公共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能够解析数据?还有其他想法可以正确解决此问题吗?
答案 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。