简体   繁体   English

角度4异步管道不起作用

[英]angular 4 async pipe is not working

I'm trying to use async pipe but there is no data being displayed. 我正在尝试使用异步管道,但是没有数据正在显示。 I'm logging the data that is coming from the server and it shows up fine in the console. 我正在记录来自服务器的数据,它在控制台中显示良好。 But for some reason I can't get the async to work. 但是由于某种原因,我无法使异步工作。

shift.service.ts 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 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 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>

The buttons don't even show up even though the service is providing with the value of true. 即使服务提供的值为true,按钮甚至不会显示。 I do get the div to show up but there is no value for shiftLive.active, or the shiftLive.totalNumberOfTicketsSold. 我确实显示了div,但shiftLive.active或shiftLive.totalNumberOfTicketsSold没有任何价值。

I guess you return an undefined value in your checkShiftStatus method from shift.service.ts 我猜你从shift.service.ts在checkShiftStatus方法中返回了一个未定义的值

return Promise.resolve(this.shift);

You should refactor your method this way : 您应该以这种方式重构方法:

checkShiftStatus(): Observable<Shift>{
  return this.httpClient.get<Shift>('http://localhost:8080/shift/isopen')
}

And then do something with your data in the shift.component.ts and shift.component.html : 然后对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>

You're resolving the promise before the result comes in asynchronously and promises only resolve once. 您要在结果异步输入之前解决承诺,并且承诺只能解决一次。 You need to return the unresolved promise and wait for the result to come in and then resolve your promise, like this: 您需要返回未解决的承诺,并等待结果输入,然后解决您的承诺,如下所示:

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;
}

And then your use of promises is all wrong in your component. 然后,您对诺言的使用在您的组件中都是错误的。 You're defining and setting variables that are outside the scope. 您正在定义和设置范围之外的变量。 The async pipe handles all of this for you. 异步管道为您处理所有这些。

or better yet, don't use the promise at all since observables are way better 或更好,因为可观察性更好,所以根本不使用承诺

service: 服务:

// 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);
   });
}

component: 零件:

// 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();

template: 模板:

//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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM