我正在尝试使用异步管道,但没有显示数据。我正在记录来自服务器的数据,它在控制台中显示正常。但由于某种原因,我无法让异步工作。
shift.service.ts
import { Injectable } from '@angular/core';
import { Shift } from '../shift/shift';
import { HttpClient } from '@angular/common/http';
@Injectable()
export class ShiftService {
constructor(private shift:Shift, private httpClient:HttpClient
) { this.checkShiftStatus();}
checkShiftStatus():Promise<Shift>{
this.httpClient.get<Shift>('http://localhost:8080/shift/isopen')
.subscribe((data) => {
this.shift = data;
console.log(this.shift);
},
error => {
console.error('Something went wrong while trying to check the shift!');
});
return Promise.resolve(this.shift);
}
}
shift.component.ts
import { Component, OnInit } from '@angular/core';
import { Shift } from './shift';
import { ShiftService } from '../services/shift.service';
@Component({
selector: 'app-shift',
templateUrl: './shift.component.html',
styleUrls: ['./shift.component.css']
})
export class ShiftComponent implements OnInit {
isShiftOpen:Promise<boolean>;
shiftLive:Promise<Shift>;
constructor(private shiftService: ShiftService, public shift:Shift) { }
ngOnInit() {
this.isShiftOpen = this.getShift().then(shift => this.shift.active = shift.active);
this.shiftLive = this.shiftService.checkShiftStatus();
}
getShift(){
return this.shiftService.checkShiftStatus().then(shift => this.shift = shift);
}
}
shift.component.html
<md-grid-list *ngIf="isShiftOpen | async" cols="2" rowHeight="100px">
<md-grid-tile>
<button md-raised-button [disabled]='isShiftOpen' color="primary">Open Shift</button>
<button md-raised-button [disabled]='!isShiftOpen' color="warn">Close Shift</button>
</md-grid-tile>
</md-grid-list>
<md-card class="card">
<md-card-title>
Shift Stats:
</md-card-title>
<md-card-content>
</md-card-content>
</md-card>
<!-- <div *ngIf="(shiftLive | async)?.notnull; else loading"> -->
<div *ngIf="shiftLive | async">
<p> Shift status: {{ shiftLive.active }} </p>
<p> Tickets Sold: {{ shiftLive.totalNumberOfTicketsSold }} </p>
</div>
<ng-template #loading>Loading Data...</ng-template>
即使服务提供的值为true,按钮也不会显示。我确实让div显示但是shiftLive.active或者shiftLive.totalNumberOfTicketsSold没有任何价值。
答案 0 :(得分:0)
我猜你在shift.service.ts中的checkShiftStatus方法中返回一个未定义的值
return Promise.resolve(this.shift);
你应该这样重构你的方法:
checkShiftStatus(): Observable<Shift>{
return this.httpClient.get<Shift>('http://localhost:8080/shift/isopen')
}
然后在shift.component.ts和shift.component.html:
中对您的数据执行某些操作export class ShiftComponent implements OnInit {
shift: any;
constructor(private shiftService: ShiftService, public shift:Shift) { }
ngOnInit() {
this.getShift();
}
getShift(): void {
this.shiftService.checkShiftStatus()
.subscribe(shift => this.shift = shift);
}
isActive(): boolean {
return this.shift && this.shift.active;
}
ticketsSold(): number {
return this.shift ? this.shift.totalNumberOfTicketsSold : 0;
}
}
<md-grid-list *ngIf="isActive()" cols="2" rowHeight="100px">
<md-grid-tile>
<button md-raised-button [disabled]='isActive()' color="primary">Open Shift</button>
<button md-raised-button [disabled]='!isActive()' color="warn">Close Shift</button>
</md-grid-tile>
</md-grid-list>
<md-card class="card">
<md-card-title>
Shift Stats:
</md-card-title>
<md-card-content>
</md-card-content>
</md-card>
<!-- <div *ngIf="shift?.notnull; else loading"> -->
<div *ngIf="shift">
<p> Shift status: {{ isActive() }} </p>
<p> Tickets Sold: {{ ticketsSold() }} </p>
</div>
<ng-template #loading>Loading Data...</ng-template>
答案 1 :(得分:0)
您在异步进入结果之前解决了承诺,承诺只解决一次。您需要返回未解决的承诺并等待结果进入然后解决您的承诺,如下所示:
checkShiftStatus():Promise<Shift>{
let promise = new Promise<Shift>();
this.httpClient.get<Shift>('http://localhost:8080/shift/isopen')
.subscribe((data) => {
this.shift = data;
promise.resolve(this.shift);
console.log(this.shift);
},
error => {
console.error('Something went wrong while trying to check the shift!');
});
return promise;
}
然后你的使用承诺在你的组件中都是错误的。您正在定义和设置范围之外的变量。异步管道为您处理所有这些。
或者更好的是,不要使用承诺,因为可观察性更好
服务:
// just return the observable stream and don't subscribe, let async handle your subscriptions
checkShiftStatus():Observable<Shift>{
return this.httpClient.get<Shift>('http://localhost:8080/shift/isopen')
.do((data) => {
// you really shouldn't do this. statefulness like this is a sign of bad design
this.shift = data;
console.log(this.shift);
}).catch(err => {
console.log('make sure to handle this error');
Observable.throw(err);
});
}
成分:
// only set this once so that we don't make the same http call over and over, we have all the data we need here (the $ syntax is standard for denoting an observable)
this.shiftLive$ = this.shiftService.checkShiftStatus();
模板:
//only use async once to avoid multiple subscriptions, and declare it "as" whatever you want, and then you have access to it throughout the template, you can still use your loading template as you want.
<ng-container *ngIf="shiftLive$ | async as shiftLive; else loading">
<md-grid-list *ngIf="shiftLive.active" cols="2" rowHeight="100px">
<md-grid-tile>
<button md-raised-button [disabled]='shiftLive.active' color="primary">Open Shift</button>
<button md-raised-button [disabled]='!shiftLive.active' color="warn">Close Shift</button>
</md-grid-tile>
</md-grid-list>
<md-card class="card">
<md-card-title>
Shift Stats:
</md-card-title>
<md-card-content>
</md-card-content>
</md-card>
<div>
<p> Shift status: {{ shiftLive.active }} </p>
<p> Tickets Sold: {{ shiftLive.totalNumberOfTicketsSold }} </p>
</div>
<ng-template #loading>Loading Data...</ng-template>
</ng-container>