2017-09-26 103 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