Angular Httpclient 服务返回数据,但数据打印失败。如何强制等待直到订阅完成

Angular Httpclient service returning data, but printing of the data fails. How to force to await until subscription is finished

我正在构建会员管理应用程序。

我有一个组件可以打印成员的详细信息。

该组件注入了 2 个服务,一个用于检索会员详细信息,另一个用于检索所有国家/地区描述的数组。

我想根据memberdetails中存储的countryid解析国家。

member-details.component.ts:

  memberDetails: Observable<MemberDetailsModel>;
  memberDetailsData: MemberDetailsModel;
  countryList: Country[]  = new Array();
  memberid: number;
  inputsMemberDisabled: boolean;

  constructor(private route: ActivatedRoute, private memberService: MemberService, private globalDataService: GlobalDataService, private router: Router) {
  }


  ngOnInit() {
    this.inputsMemberDisabled = true;
    this.memberid = this.route.snapshot.params['id'];

    console.log('calling getCountryList: ' + this.countryList);
    this.countryList = this.globalDataService.getCountryList();
    this.getMemberDetails();

  }


  getMemberDetails() {
    this.memberService.getMemberDetails(this.memberid).subscribe(response => {
      this.memberDetails= response;
      this.memberDetailsData = response;
    });
    console.log("getMemberDetails() countrylist: "+ this.countryList)
  }

  mapCountry(id: number): Country {
    console.log('mapCountry: ' + this.countryList);
    for (var i = 0, len = this.countryList.length; i < len; i++) {
      let country = this.countryList.pop();
      if (id === country.id) {
        return country;
      }

    }
    return new Country();

到目前为止,检索 member-details 工作正常。但我不能解决这个国家。它说未定义!

member-details.component.ts(第 21 行 --)

如果我检查 global-data 服务的输出,我可以看到正在检索国家 Objects。 我假设 html-component 试图在 global-data 服务中的 Observable 完成之前渲染国家(至少控制台日志在 member-details 中给我空数组)。 component.ts)

global-data-service.ts

  country: Observable<Country[]>;
  countryList: Country[] = [];

  constructor(private http: HttpClient) {
  }

  getCountryList(): Country[] {
    if (this.countryList.length < 1) {
      console.log("<1");
      this.initializeCountryList().subscribe((res => {
        console.log('countrylist result: ' + res);
        this.countryList = res;
        console.log('countrylist result2: ' + res);
      }));
    }

    return this.countryList
  }

  initializeCountryList(): Observable<Country[]> {
    if (this.countryList.length < 1) {
      //return this.http.get(`${this.baseUrl}/countrylist`).pipe(map(res => res as Country[]
      return this.http.get(`${this.baseUrl}/countrylist`).pipe(map(res => res as Country[]));
}

Country.ts:

export class Country {
  id: number;
  country: string; //This is the data I want to get
  alpha2Code: string;
  alpha3Code: string;
  numericcode: string;

}

我真的很沮丧,因为我已经在一个多星期内尝试了多种方法 :) 但没有成功。

感谢您的建议。

编辑: MemberDetailsModel:

import {Memberstate} from "./memberstate";
import {Member} from "./member";
import {Contactinformation} from "./contactinformation";
import {Paymentinformation} from "./paymentinformation";


export class MemberDetailsModel {
  member: Member;
  state: Memberstate;
  contactinformations: Contactinformation[];
  paymentinformation: Paymentinformation;
}

成员:

import { Membertype} from "../enums/membertype.enum";

export class Member {
  //properties from mm_mem

ber
      id: number;
      memberid: number;
      mainmemberid: number;
      membertype: Membertype;
      firstname: string;
      surname: string;
      birthdate: Date;
      nationality1id: number;
      nationality2id?: number;
      subscriptiondate?: Date;
      recorddate?: Date;
      defaultlanguage:String;
      billcategory: String;
      comment?: String;

    }

编辑2: member-details.component.html:

<mat-card class="example-card">
  <mat-card-header>
    <div mat-card-avatar>
      <i class="material-icons md-36">
        face
      </i>
    </div>
    <mat-card-title>Persönliche Daten</mat-card-title>
    <mat-card-subtitle>Stammdaten des Mitglieds</mat-card-subtitle>
    <div>
      <i class="material-icons">
        edit
      </i>
      <i class="material-icons">
        save
      </i>
    </div>
  </mat-card-header>
  <mat-card-content>
    <mat-form-field>
      <input [disabled]="inputsMemberDisabled" matInput placeholder="Vorname" required [(ngModel)]="memberDetailsData.member.firstname" name="firstname">
    </mat-form-field>
    <mat-form-field>
      <input [disabled]="inputsMemberDisabled" matInput placeholder="Nachname" value="{{memberDetailsData.member.surname}}">
    </mat-form-field>
    <mat-form-field>
      <input [disabled]="true" matInput placeholder="MitgliedsNr." value="{{memberDetailsData.member.memberid}}">
    </mat-form-field>
    <mat-form-field>
      <input [disabled]="inputsMemberDisabled" matInput placeholder="Mitgliedsart" value="{{memberDetailsData.member.membertype}}">
    </mat-form-field>
    <mat-form-field>
      <input [disabled]="inputsMemberDisabled" matInput placeholder="Hauptmitglied" value="{{memberDetailsData.member.mainmemberid}}">
    </mat-form-field>
    <mat-form-field>
      <input [disabled]="inputsMemberDisabled" matInput placeholder="Geburtsdatum" value="{{memberDetailsData.member.birthdate | date}}">
    </mat-form-field>
    <!--mat-form-field>
      <input [disabled]="inputsMemberDisabled" matInput placeholder="Nationalität 1" value="{{mapCountry(memberDetailsData.member.nationality1id).country}}">
    </mat-form-field-->
    <mat-form-field>
      <input [disabled]="inputsMemberDisabled" matInput placeholder="Nationalität 1" value="{{memberDetailsData.member.nationality1id}}">
    </mat-form-field>
    <mat-form-field>
      <input [disabled]="inputsMemberDisabled" matInput placeholder="Nationalität 2" value="{{memberDetailsData.member.nationality2id}}">
    </mat-form-field>
    <mat-form-field>
      <input [disabled]="inputsMemberDisabled" matInput placeholder="Anmeldedatum" value="{{memberDetailsData.member.subscriptiondate | date}}">
    </mat-form-field>
    <mat-form-field>
      <input [disabled]="inputsMemberDisabled" matInput placeholder="Erfassungsdatum" value="{{memberDetailsData.member.recorddate | date}}">
    </mat-form-field>
    <mat-form-field>
      <input [disabled]="inputsMemberDisabled" matInput placeholder="Bevorzugte Sprache" value="{{memberDetailsData.member.defaultlanguage}}">
    </mat-form-field>
    <mat-form-field>
      <input [disabled]="inputsMemberDisabled" matInput placeholder="Rechnungskategorie" value="{{memberDetailsData.member.billcategory}}">
    </mat-form-field>
    <mat-form-field class="example-full-width">
      <textarea [disabled]="inputsMemberDisabled" matInput placeholder="Kommentar" value="{{memberDetailsData.member.comment}}"></textarea>
    </mat-form-field>

  </mat-card-content>
  <mat-card-actions>
    <button mat-raised-button color="primary" [disabled]="!inputsMemberDisabled" (click)="toggleDisabledInputs()">Bearbeiten</button>
    <button mat-button mat-raised-button color="warn" [disabled]="inputsMemberDisabled" (click)="updateMemberInformation()">Speichern</button>
  </mat-card-actions>
</mat-card>
  • global-data-service 服务的 getCountryList() 函数中,您正在 returning 一个 Country 的普通数组,但它是从 Observable 内部检索的。 return 服务中的可观察值也会更好地为您服务。这样,我们可以确保 member-details 组件中的 this.countryList 变量被分配了正确的值。

全局数据-service.ts

getCountryList(): Observable<Country[]> {
  const result = Subject<Country[]>();

  if (this.countryList.length < 1) {
    this.initializeCountryList().subscribe(
      res => {
        this.countryList = res;
        result.next(res);
      }
    );
  }

  return result.asObservable();
}

成员-details.component.ts

ngOnInit() {
  this.inputsMemberDisabled = true;
  this.memberid = this.route.snapshot.params['id'];

  this.globalDataService.getCountryList().subscribe(countries => { this.countryList = countries });
  this.getMemberDetails();
}
  • 在 HTML 模板中,使用 optional chaining operator (?.) 以确保在访问变量的属性之前先定义该变量。因此,将 memberDetailsData.member 的所有实例替换为 memberDetailsData?.member。这相当于在访问它的属性之前检查 memberDetailsData 是否被定义。如果您需要检查子属性是否存在,您可以继续 memberDetailsData?.member?.firstname.

您可以在打印数据的模板部分使用 *ngIf 指令来检查数据是否已设置。如果设置它将显示数据,否则该块将不会在 DOM 中呈现。喜欢

<div *ngIf = "memberDetailsData">

  <!-- Template part goes here -->

</div>

或者您可以在访问对象的成员时使用三元运算。

memberDetailsData?.member 同时将值分配给输入字段。

希望能解决您的问题