我正在尝试创建天气应用。在需要接收为视图操作所需的数据之前,需要进行两个不同的api调用。
我创建了一个服务,该服务进行这些api调用并设置全局变量以供从不同组件访问。第一个调用是地理位置api。收到纬度和经度参数后,我可以再次调用天气api。
我遇到的问题是我的组件正在尝试在天气api调用完成之前访问全局变量,从而向我呈现未定义的变量。
我尝试使用async / await,但无法使其正常工作,最近才找到一个forkJoin rxjs方法。
当前,我所做的解决方案是使用setTimeout函数等待大约1秒钟,然后再进行下一行代码。我不认为这是执行此操作的最佳方法,但它确实有效。
有没有更好的方法可以研究并尝试?
main-component.ts
currentlyForecast: string;
lat: number;
long: number;
ngOnInit() {
this.getGeo();
}
getGeo() {
this.weather.getGeo()
.subscribe((data: any) => {
this.lat = data.latitude;
this.long = data.longitude;
this.getWeather(this.lat, this.long);
});
}
getWeather(lat, long) {
let location = { latitude: lat, longitude: long };
this.weather.getWeather(location);
setTimeout(() => {
this.currentlyForecast = this.weather.currentlyForecast;
console.log(this.currentlyForecast);
}, 700);
}
weather.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
@Injectable({
providedIn: 'root'
})
export class WeatherService {
// Weather parameters
public currentlyForecast: any;
public dailyForecast: any;
public hourlyForecast: any;
public minutelyForecast: any;
private weatherUrl = 'http://localhost:3000/weather/data';
private geoLocationUrl = 'http://localhost:3000/weather/geo';
constructor(private http: HttpClient) {
}
getGeo() {
return this.http.get(this.geoLocationUrl);
}
getWeather(location) {
return this.http.post(this.weatherUrl, location, httpOptions)
.subscribe((data: any) => {
console.log(data)
this.currentlyForecast = data.currently;
this.dailyForecast = data.daily;
this.hourlyForecast = data.hourly;
this.minutelyForecast = data.minutely;
});
}
}
答案 0 :(得分:1)
请执行以下更改代码。 :
// modify your service like below :
getWeather(location) {
return this.http.post(this.weatherUrl, location, httpOptions)
.map((data: any) => {
console.log(data)
// you can keep these variables if needed here or
// move them to component file
this.currentlyForecast = data.currently;
this.dailyForecast = data.daily;
this.hourlyForecast = data.hourly;
this.minutelyForecast = data.minutely;
return this.currentlyForecast; // returning this because you have used in componenet file
});
}
// Now in component modify your method like below :
getWeather(lat, long) {
let location = { latitude: lat, longitude: long };
this.weather.getWeather(location).subscribe((result:any)=>{
//result will contain currentlyForecast value
this.currentlyForecast = result;
console.log(this.currentlyForecast);
});
}
答案 1 :(得分:0)
我建议进行以下更改:
此方法返回承诺,Promise
具有then
和catch
回调。
getWeather(location): Promise<any> {
return this.http.post(this.weatherUrl, location, httpOptions).ToPromise();
}
在您的weather.service.ts
中添加此方法:
public setData(data: any): void {
this.currentlyForecast = data.currently;
this.dailyForecast = data.daily;
this.hourlyForecast = data.hourly;
this.minutelyForecast = data.minutely;
}
在您的main-component.ts
getWeather(lat, long) {
let location = { latitude: lat, longitude: long };
this.weather.getWeather(location)
.then((data) => {
this.weather.setData(data);
this.currentlyForecast = this.weather.currentlyForecast;
console.log(this.currentlyForecast);
}).catch((error) => {
console.error(error);
});
}
我们可以在以下位置看到它的工作:
https://stackblitz.com/edit/angular-xodqxj?embed=1&file=src/app/weather.service.ts
答案 2 :(得分:0)
getWeather(location) {
return this.http.post(this.weatherUrl, location, httpOptions)
.pipe(
map((data: any) => {
console.log(data)
this.currentlyForecast = data.currently;
this.dailyForecast = data.daily;
this.hourlyForecast = data.hourly;
this.minutelyForecast = data.minutely;
console.log(this.currentlyForecast);
return this.currentlyForecast;
})
);
}