2017-09-26 108 views
0

我想使用异步管道,但没有显示数据。我正在记录来自服务器的数据,并在控制台中显示正常。但出于某种原因,我无法使异步工作。角度4异步管道不工作

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

您正在解决诺言,结果出现异步,并承诺只解决一次。你需要返回未解决的承诺,并等待结果进来,然后解决你的承诺,像这样:

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> 
+0

我提出了您的建议更改并尝试运行该程序。但结束了一个错误,说明错误TypeError:无法读取对象.val [作为updateRenderer](ShiftComponent.html:18) 在Object.debugUpdateRenderer [作为updateRenderer]未定义 属性'活动'。 在服务中,我使用this.httpClient.get ('http:// localhost:8080/shift/isopen');现在只有这么多的代码。甚至没有试图捕捉错误。有什么建议么?谢谢。 – Saurin

+0

包含* ngIf =“shiftLive $ | async as shiftLive;否则在div部分加载它开始工作正常。但你说得对它做出多个http调用服务器。 – Saurin

+0

您只需向我展示一次订阅。没有必要将可观察到的流分成两个调用。所有需要的信息都在同一个电话 – bryan60

0

我猜你在checkShiftStatus方法从shift.service.ts

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> 
+0

异步管道是更清洁,更安全的d订阅观察对象的首选方法 – bryan60