重新加载时,Angular应用程序中断。可能是生命周期挂钩错误

时间:2018-07-12 17:33:27

标签: angular typescript firebase

我有一个Angular应用程序,它将firebase uid发布到我的服务器,然后返回一个响应,其中包含要在数据表中显示的对象数组。

当我从默认页面转到数据表时,它可以正常工作,但是当我重新加载应用程序时,它中断了,我得到了Error trying to diff '[object Object]'. Only arrays and iterables are allowed

我认为该错误是因为它返回错误消息,并且无法在表中显示。

我认为问题在于,当我重新加载页面时,它没有获取用户uid,因此我发送给服务器的参数是未定义的,因此它将返回该错误。

所以,我的问题是在向服务器发送请求之前,如何在重新加载数据表组件时获取用户uid。

服务:

private user: Observable<firebase.User>;
public userDetails: firebase.User = null;
uid: any;

  constructor(private http: HttpClient,
              private authFirebase : AngularFireAuth) {
                this.user = authFirebase.authState;
                this.user.subscribe(
                  (user) => {
                    if (user) {
                      this.userDetails = user;
                      console.log(this.userDetails.email);
                      this.uid = this.userDetails.uid;
                    }
                    else {
                      this.userDetails = null;
                    }
                  }
                );
               }

getFullRegistryUniversity(): Observable<DegreeDetails[]> {
    console.log(`serviceuid: ${this.uid}`);
    let uidString = {
      "uid" : this.uid
    }
    return this.http.post<DegreeDetails[]>(this.serviceUrl, uidString)
  }

组件:

export class GraduateComponent implements OnInit {

  dataSource = new UserDataSource(this.registryService);
  displayedColumns = ['graduateRut', 'major', 'university', 'gradYear'];

  constructor(private registryService: RegistryService) { }

  ngOnInit() {}

}

export class UserDataSource extends DataSource<any> {
  constructor(private registryService: RegistryService) {
    super();
  }
  connect(): Observable<DegreeDetails[]> {

    return this.registryService.getFullRegistryUniversity();
  }
  disconnect() {}
}

编辑:

html:

<div>
  <mat-table [dataSource]="dataSource">
    <ng-container matColumnDef="graduateRut">
      <mat-header-cell *matHeaderCellDef> RUT </mat-header-cell>
      <mat-cell *matCellDef="let degreeDetails"> {{degreeDetails.graduateRut}} </mat-cell>
    </ng-container>
    <ng-container matColumnDef="major">
      <mat-header-cell *matHeaderCellDef> E-Mail </mat-header-cell>
      <mat-cell *matCellDef="let degreeDetails"> {{degreeDetails.major}} </mat-cell>
    </ng-container>
    <ng-container matColumnDef="university">
      <mat-header-cell *matHeaderCellDef> University </mat-header-cell>
      <mat-cell *matCellDef="let degreeDetails"> {{degreeDetails.university}} </mat-cell>
    </ng-container>
    <ng-container matColumnDef="gradYear">
      <mat-header-cell *matHeaderCellDef> GradYear </mat-header-cell>
      <mat-cell *matCellDef="let degreeDetails"> {{degreeDetails.gradYear}} </mat-cell>
    </ng-container>
    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
  </mat-table>
</div>

1 个答案:

答案 0 :(得分:2)

您假设您是正确的,您在初始化uid之前正在调用API,因此会出现错误。
我们可以尝试通过多种方法来解决此问题,我将提供一个解决方法。
首先,将服务中的uid更改为BehaviorSubject:

uid = new BehaviorSubject<any>(null);

现在在构造函数中:

this.user.subscribe(
  (user) => {
    if (user) {
      this.userDetails = user;
      console.log(this.userDetails.email);
      this.uid.next(this.userDetails.uid);
    }
    else {
      this.userDetails = null;
    }
  }
);

应更改为支持BehviorSubject的http发布请求:

getFullRegistryUniversity(): Observable<DegreeDetails[]> {
    let uidString = {
      "uid" : this.uid.value // <-- here
    }
    return this.http.post<DegreeDetails[]>(this.serviceUrl, uidString)
  }

并添加此get方法:

getUidObservable() {
 return this.uid.asObservable()
}

在组件中,不要一开始就初始化数据源,而是等待UID变为可行的值。

dataSource: UserDataSource;

ngOnInit() {
 this.registryService.getUidObservable().subscribe(_uid => {
  if(_uid !== null) {
     dataSource = new UserDataSource(this.registryService);
   }
 }
}

最后一件事,在您的html中,添加到wrap div中:

<div *ngIf="dataSource">

希望它能解决并解决您的问题。也许会有更快的方法,但是我认为这可以确保您的通话安全。