我正在构建一个日历应用程序,它使用http.get从后端获取某一天的信息(当前后端是服务器模拟)。我的问题是,异步http.get的速度不足以在页面呈现期间传递数据,并且一旦数据到达,数据就不会显示,我相信更改检测应该正常选择。 关于http.get方法,我遵循Angular.io上的示例,在此处找到https://angular.io/guide/http#subscribe
代码:
FetchService:
getDayInfo(date: string): Observable<any> {
return this.http.get(url)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body; // not really doing much with the data here yet
}
component.ts:
dayData: any[];
dayInfo: any[];
constructor(private fetcher: FetchService) {}
ngOnInit(): void {
this.getDay();
setTimeout(() => { this.setDayData(); }, 10);
// the setTimeout is mostly here for testing, tried to sort of set the
// Data after the async http.get was done
}
getDay () {
this.fetcher.getDayInfo(this.date).subscribe(
body => this.dayInfo = body,
);
}
setDayData() {
if (this.dayInfo) {
this.dayData = this.dayInfo;
console.log(this.dayData);
// and some more things that only matter for some CSS markup
}
}
component.html:
<!--{{ dayInfo[0].type.name }}-->
<div *ngIf="dayData">
<div *ngFor="let data of dayData">
<p>{{ data.type.name }}</p>
</div>
</div>
<div *ngIf="!dayData">
<p>Loading</p>
</div>
每天总是只显示加载,在超时后,控制台填充实际和正确的dayData,网站仍然只显示正在加载。 如果我在html中的{{dayInfo [0] .type.name}}中发表评论,我首先会在&#34; Loading&#34;并且一个错误说明dayInfo的控制台是未定义的,然后一点一点,填充日期,显示加载和我想要的数据,尽管控制台充满了上述错误。
现在,由于我无法加速异步http.get,有没有办法触发更改检测以获取dayData中的更改?或者任何其他解决方法让我显示正确的数据?
PS:在setDayData中控制日志记录dayData时我注意到的另一件事是有时日志没有列出所有日期,这意味着它可能显示一个月的前27天,但是没有关于日期的日志条目休息。不确定是什么原因引起的。
编辑: 在第一个评论和第一个答案之后,我将component.ts中的getDay方法更改为:
getDay () {
this.fetcher.getDayInfo(this.date).subscribe(
body => {
this.dayInfo = body;
this.setDayData();
);
}
现在我在&#34; PS中描述了奇怪的行为:&#34;上面已经消失,所有日子都在日志中显示,尽管它们混在一起(不再按时间顺序排列)。 网站仍然只显示&#34;正在加载&#34;虽然并且没有更新到正确的数据。我可能需要在这里手动触发变化检测。
答案 0 :(得分:3)
您的超时可能会在您获取数据之前触发。您可能希望从getDayInfo订阅块的主体中调用它,而不是从ngOnInit调用setDayData。
这将确保您获得数据,并在收到数据后调用您的后续方法。
ngOnInit(): void {
this.getDay();
}
getDay () {
this.fetcher.getDayInfo(this.date).subscribe(
body => {
this.dayInfo = body;
this.setDatData();
}
);
}
关于获取未定义的另一个问题 - 这是因为在首次显示模板时你有一个空数组(在运行setDayData方法之前它没有设置)。如果您真的想在屏幕上显示,也可以将其包装在ngIf中。这样你知道你也有数据。
答案 1 :(得分:1)
而不是使用Timeout,最好在回调中调用this.setData()
,就像William指出的那样。这是因为我们实际上并不知道异步请求需要多长时间。
ngOnInit(): void {
this.getDay();
}
getDay () {
this.fetcher.getDayInfo(this.date).subscribe(
body => {
this.dayInfo = body;
this.setDatData(); // here
}
);
}
此后,由于某种原因,未运行更改检测,因此我们需要手动触发它。这可以通过ChangeDetectorRef
实现,我们从@angular/core
导入,将其注入构造函数:
constructor(private ref: ChangeDetectorRef) { }
然后在setDayData()
setDayData() {
if (this.dayInfo) {
this.dayData = this.dayInfo;
console.log(this.dayData);
this.ref.detectChanges(); // here!
}
}