【问题标题】:Wait before display data with {HttpClient} - typescript - Angular在使用 {HttpClient} 显示数据之前等待 - typescript - Angular
【发布时间】:2021-05-06 13:20:48
【问题描述】:

4 天以来,我一直在尝试显示数据,但没有任何运行。 我的目标是从工厂的内部服务器接收数据。所以,一些西门子 CPU 以 CSV 文件格式发送数据,我在

line.service.ts

import {Subject} from 'rxjs';
import {HttpClient} from '@angular/common/http';
import {Injectable} from '@angular/core';

@Injectable()
export class LineService{

  public lines: RcvData[] = [];

  constructor(private http: HttpClient) {
    this.getData();
  }

  lineSubject = new Subject<any[]>();

  getData(): void {
    const lists: string[] = [
      'assets/donnee-l1.csv',
      'assets/donnee-l2.csv',
      'assets/donnee-l3.csv',
      'assets/donnee-l4.csv',
      'assets/donnee-l5.csv',
      'assets/donnee-l6.csv'
    ];
    for (const list of lists) {
      this.http.get(list, {responseType: 'text'})
        .subscribe(data => {
          const csvToRowArray = data.split('\n');
          const lastRow = csvToRowArray[csvToRowArray.length - 2];
          const row = lastRow.split(',');
          this.lines.push(new RcvData(
            parseInt(row[0], 10),
            row[1], row[2], row[3], row[4], row[5],
            parseInt(row[6], 10),
            parseInt(row[7], 10),
            parseInt(row[8], 10),
            parseInt(row[9], 10),
            parseFloat(row[10]),
            parseFloat(row[11]),
            parseFloat(row[12]),
            parseFloat(row[13]),
            parseFloat(row[14]))
          );
          if(this.lines.length === 6){
            this.isLoading = true;
          }
          console.log(this.isLoading);
          console.log(this.lines.length);
        }, error => {
          console.log(error);
        });
    }
  }

  emitLineSubject(): void {
    this.lineSubject.next(this.lines.slice());
  }
  getLineById(id: number): RcvData{
    const line = this.lines.find(
      (lineObject) => {
        return lineObject.id === id;
      }
    );
    return line;
  }
}

class RcvData{
  id: number;
  date: string;
  utcTime: string;
  refCharge: string;
  refDecharge: string;
  quantiteEnCours: string;
  quantiteHoraireReel: number;
  quantiteHoraireTheorique: number;
  quantitePosteReel: number;
  quantitePosteTheorique: number;
  trpHeureReel: number;
  trpPosteReel: number;
  trpObjectif: number;
  consoAir: number;
  consoElec: number;


  constructor(
    id: number,
    date: string,
    utcTime: string,
    refCharge: string,
    refDecharge: string,
    quantiteEnCours: string,
    quantiteHoraireReel: number,
    quantiteHoraireTheorique: number,
    quantitePosteReel: number,
    quantitePosteTheorique: number,
    trpHeureReel: number,
    trpPosteReel: number,
    trpObjectif: number,
    consoAir: number,
    consoElec: number)
  {
    this.id = id;
    this.date = date;
    this.utcTime = utcTime;
    this.refCharge = refCharge;
    this.refDecharge = refDecharge;
    this.quantiteEnCours = quantiteEnCours;
    this.quantiteHoraireReel = quantiteHoraireReel;
    this.quantiteHoraireTheorique = quantiteHoraireTheorique;
    this.quantitePosteReel = quantitePosteReel;
    this.quantitePosteTheorique = quantitePosteTheorique;
    this.trpHeureReel = trpHeureReel;
    this.trpPosteReel = trpPosteReel;
    this.trpObjectif = trpObjectif;
    this.consoAir = consoAir;
    this.consoElec = consoElec;
  }
}

现在,在这个 .ts 中,我拆分 CSV 数据以拥有我的 6 条生产线的对象。我为我的 html 页面发送数据,以显示它。我用这个组件读取数据:

single.line.components.ts

import { Component, OnInit } from '@angular/core';
import { LineService } from '../services/line.service';
import { ActivatedRoute } from '@angular/router';
import {async} from 'rxjs-compat/scheduler/async';

@Component({
  selector: 'app-single-line',
  templateUrl: './single-line.component.html',
  styleUrls: ['./single-line.component.scss']
})
export class SingleLineComponent implements OnInit {

  name = 'Ligne...';
  status = 'éteint';
  date_jour = '2021-01-01';
  heure_act = '00:00:00';
  reference_charge = 'ST00S00';
  reference_decharge = 'ST11S11';
  quantite_produite = '1/1000';
  quantite_h_reel = 0;
  quantite_h_th = 0;
  quantite_p_reel = 0;
  quantite_p_th = 0;
  trp_h_reel = 0;
  trp_p_reel = 0;
  trp_objectif = 0;
  conso_air = 0;
  conso_elec = 0;

  private activatedRoute: ActivatedRoute;

  constructor(private lineService: LineService,
              private route: ActivatedRoute) {
              this.activatedRoute = route;
  }

  ngOnInit(): void {
    this.activatedRoute.params.subscribe(params => {
      const id = params.id;
      this.name = this.lineService.getLineById(+id).refCharge;
      this.status = this.lineService.getLineById(+id).date;
      this.date_jour = this.lineService.getLineById(+id).date;
      this.heure_act = this.lineService.getLineById(+id).utcTime;
      this.reference_charge = this.lineService.getLineById(+id).refCharge;
      this.reference_decharge = this.lineService.getLineById(+id).refDecharge;
      this.quantite_produite = this.lineService.getLineById(+id).quantiteEnCours;
      this.quantite_h_reel = this.lineService.getLineById(+id).quantiteHoraireReel;
      this.quantite_h_th = this.lineService.getLineById(+id).quantiteHoraireTheorique;
      this.quantite_p_reel = this.lineService.getLineById(+id).quantitePosteReel;
      this.quantite_p_th = this.lineService.getLineById(+id).quantitePosteTheorique;
      this.trp_h_reel = this.lineService.getLineById(+id).trpHeureReel;
      this.trp_p_reel = this.lineService.getLineById(+id).trpPosteReel;
      this.trp_objectif = this.lineService.getLineById(+id).trpObjectif;
      this.conso_air = this.lineService.getLineById(+id).consoAir;
      this.conso_elec= this.lineService.getLineById(+id).consoElec;
    });
  }
}

最后,我的 HTML 页面:

<div class="container-fluid">
  <div [ngClass]="{'list-group-item': true,
                'list-group-item-success': status === 'allumé',
                'list-group-item-danger' : status === 'éteint',
                'list-group-item-warning' : status === 'changement'
                }">
    <h1>
      <p *ngIf="status === 'allumé'"> {{ name }} | en production
        <span class="glyphicon glyphicon-ok"></span>
      </p>
      <p *ngIf="status === 'éteint'">{{ name }} |  à l'arrêt
        <span class="glyphicon glyphicon-remove"></span>
      </p>
      <p *ngIf="status === 'changement'">{{ name }} | changement en cours
        <span class="glyphicon glyphicon-refresh"></span>
      </p>
    </h1>
  <div class="row h3">

    <div class="col-sm-6 list-group-item-text text-center">
      <p> Référence en cours de chargement : {{ reference_charge }}</p>
      <p> Référence en cours de déchargement : {{ reference_decharge }}</p>
    </div>
  </div>

    <div class="row list-group-item-text text-center h4">
      <div class="col-sm-3 text-center">
        <p>Quantité de pièces totale : {{ quantite_produite }}</p>
      </div>
      <div class="col-sm-3 text-center">
        <p>Pièces produites dans l'heure : {{ quantite_h_reel }}</p>
      </div>
      <div class="col-sm-3 text-center">
        <p>Pièces à produire par heure : {{ quantite_h_th }}</p>
      </div>
      <div class="col-sm-3 text-center">
        <p>Pièces produites sur le poste : {{ quantite_p_reel }}</p>
      </div>
      <div class="col-sm-3 text-center">
        <p>Pièces à produire sur un poste : {{ quantite_p_th }}</p>
      </div>
      <div class="col-sm-3 text-center">
        <p>TRP de l'heure: {{ trp_h_reel }}</p>
      </div>
      <div class="col-sm-3 text-center">
        <p>TRP du poste: {{ trp_p_reel }}</p>
      </div>
      <div class="col-sm-3 text-center">
        <p>TRP Objectif: {{ trp_objectif }}</p>
      </div>
      <div class="col-sm-3 text-center">
        <p>Consommation d'air: {{ conso_air }}</p>
      </div>
      <div class="col-sm-3 text-center">
        <p>Consommation électrique : {{ conso_elec }}</p>
      </div>
        </div>
    <button class="btn btn-primary" routerLink="/lines">Retour</button>
  </div>
  <app-view-graph></app-view-graph>

</div>

但问题是,当我重新加载页面时,出现错误:TypeError: Cannot read property '...' of undefined。这是因为页面正在加载,然后读取数据运行。 如果我通过导航栏更改页面并返回正确的页面,则数据就在这里。我只想在数据存在时显示页面。

我尝试了 Promise、Async、Await、SpinnerLoad,但它不起作用。

欢迎任何帮助。 谢谢

【问题讨论】:

  • 那么它在哪里失败了?它不能读取什么属性?附言你总是可以在渲染之前使用[ngIf]检查对象。

标签: javascript html angular typescript csv


【解决方案1】:

我建议让您的解决方案更具反应性。

首先不要使用 for 循环遍历所有链接,然后将它们推送到 lines[] 中,我建议采用以下方法

import {BehaviourSubject} from 'rxjs';
import {HttpClient} from '@angular/common/http';
import {Injectable} from '@angular/core';

@Injectable()
export class LineService{
  constructor(private http: HttpClient) {
    this.getData();
  }

  lineSubject = new BehaviourSubject<RcvData[]>([]);

  getData(): void {
    const lists: string[] = [
      'assets/donnee-l1.csv',
      'assets/donnee-l2.csv',
      'assets/donnee-l3.csv',
      'assets/donnee-l4.csv',
      'assets/donnee-l5.csv',
      'assets/donnee-l6.csv'
    ];
    
    combineLatest(lists.map(list => this.http.get(list, {responseType: 'text'})))
        .subscribe(listResults => {

         const parsedListResults = listResults.map(data => {
         
          const csvToRowArray = data.split('\n');
          const lastRow = csvToRowArray[csvToRowArray.length - 2];
          const row = lastRow.split(',');
          return new RcvData(
            parseInt(row[0], 10),
            row[1], row[2], row[3], row[4], row[5],
            parseInt(row[6], 10),
            parseInt(row[7], 10),
            parseInt(row[8], 10),
            parseInt(row[9], 10),
            parseFloat(row[10]),
            parseFloat(row[11]),
            parseFloat(row[12]),
            parseFloat(row[13]),
            parseFloat(row[14]))
         })
         this.lineSubject.next(parsedListResults)
      })
  }
}

class RcvData{
  id: number;
  date: string;
  utcTime: string;
  refCharge: string;
  refDecharge: string;
  quantiteEnCours: string;
  quantiteHoraireReel: number;
  quantiteHoraireTheorique: number;
  quantitePosteReel: number;
  quantitePosteTheorique: number;
  trpHeureReel: number;
  trpPosteReel: number;
  trpObjectif: number;
  consoAir: number;
  consoElec: number;


  constructor(
    id: number,
    date: string,
    utcTime: string,
    refCharge: string,
    refDecharge: string,
    quantiteEnCours: string,
    quantiteHoraireReel: number,
    quantiteHoraireTheorique: number,
    quantitePosteReel: number,
    quantitePosteTheorique: number,
    trpHeureReel: number,
    trpPosteReel: number,
    trpObjectif: number,
    consoAir: number,
    consoElec: number)
  {
    this.id = id;
    this.date = date;
    this.utcTime = utcTime;
    this.refCharge = refCharge;
    this.refDecharge = refDecharge;
    this.quantiteEnCours = quantiteEnCours;
    this.quantiteHoraireReel = quantiteHoraireReel;
    this.quantiteHoraireTheorique = quantiteHoraireTheorique;
    this.quantitePosteReel = quantitePosteReel;
    this.quantitePosteTheorique = quantitePosteTheorique;
    this.trpHeureReel = trpHeureReel;
    this.trpPosteReel = trpPosteReel;
    this.trpObjectif = trpObjectif;
    this.consoAir = consoAir;
    this.consoElec = consoElec;
  }
}

这里的主要变化是现在我们有一个静态的lines ref BehaviourSubject 形式的“live” ref,我们可以订阅它,并在有任何更改时收到通知。

import { Component, OnInit } from '@angular/core';
import { LineService } from '../services/line.service';
import { ActivatedRoute } from '@angular/router';
import {async} from 'rxjs-compat/scheduler/async';

@Component({
  selector: 'app-single-line',
  templateUrl: './single-line.component.html',
  styleUrls: ['./single-line.component.scss']
})
export class SingleLineComponent implements OnInit {

  name = 'Ligne...';
  status = 'éteint';
  date_jour = '2021-01-01';
  heure_act = '00:00:00';
  reference_charge = 'ST00S00';
  reference_decharge = 'ST11S11';
  quantite_produite = '1/1000';
  quantite_h_reel = 0;
  quantite_h_th = 0;
  quantite_p_reel = 0;
  quantite_p_th = 0;
  trp_h_reel = 0;
  trp_p_reel = 0;
  trp_objectif = 0;
  conso_air = 0;
  conso_elec = 0;




  focusedData$ = combineLatest(
  this.lineService.lineSubject.pipe(filter(x => x.length > 0)),
  this.route.params.pipe(filter(x=> !!x.id), map(x => x.id))
  ).pipe(
    map(([csvs, id]) => csvs[id])
  )

  constructor(private lineService: LineService,
              private route: ActivatedRoute) { }

}

这里有趣的部分是focusData$,我们正在组合我们在lineService 中创建的行为主题中存储的值和存储在URL 中的当前id。我们正在过滤所有无效值,然后,我们将 id 映射到适当的 csv。

从此时开始,您可以在模板中执行以下操作

<div *ngIf="focusedData$ | async">


<div> {{(focusedData$ | async).refCharge }} </div>
<div> {{(focusedData$ | async).date }} </div>
<div> {{(focusedData$ | async).utcTime }} </div>
</div>

此伪代码很可能会帮助您找到解决问题的方法,但无论如何,如果我站在您的立场上,我会考虑一种解决方案,即一次只调用一个 csv,并且在需要时,也可能是在服务的构造函数中调用 http 调用不是最明智的做法。

【讨论】:

    【解决方案2】:

    谢谢,谢谢,谢谢! 成功了,非常感谢。

    那不是“伪”代码 ^^,我只更改了 1 件事。

    this.route.params.pipe(filter(x=> !!x.id), map(x => x.id))
    

    通过

    this.route.params.pipe(filter(x=> !!x.id), map(x => x.id -1))
    

    在正确的页面中有正确的数据。 而且,仅此而已。

    感谢您的回答, 祝你有美好的一天

    【讨论】:

      猜你喜欢
      • 2020-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-01
      • 2018-09-05
      • 1970-01-01
      相关资源
      最近更新 更多