我还是 Angular 新手,目前正在学习 Angular 8。
我正在尝试创建一个简单的 API 通信服务来加载显示所需的数据。我有一个主组件和一个子组件,两者都需要获取数据来加载。
我尝试遵循几个教程,但我的常见问题是组件加载发生在 API HTTP 请求返回之前,导致未定义的数据。
我当前的 API 服务使用 HttpClient
与 API 通信
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { retry, catchError } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class ApiService {
constructor(private http: HttpClient) {}
getUserFeed(id: number): Observable<Post[]> {
return this.http
.get<Post[]>(`${API_URL}/feed`)
.pipe(
retry(3),
catchError(this.handleError)
);
}
getProfile(id: number): Observable<Profile> {
return this.http
.get<Profile>(`${API_URL}/profile/${id}`)
.pipe(
retry(3),
catchError(this.handleError)
);
}
handleError(error: any) {
let errorMessage: string;
// Set error message
(error.error instanceof ErrorEvent) ?
errorMessage = error.error.message :
errorMessage = `Error Code: ${error.code}\nMessage: ${error.message}`;
console.log(errorMessage);
return throwError(errorMessage);
}
}
API 应该返回我定义的 Posts
数组。
我在我的组件中将其称为
import { Component, OnInit } from '@angular/core';
import { UserService } from '../user/user.service';
import { ApiService } from '../api/api.service';
import { User } from '../user';
import { Post } from '../Post';
@Component({
selector: 'app-feed',
templateUrl: './feed.component.html',
styleUrls: ['./feed.component.css'],
})
export class FeedComponent implements OnInit {
posts: Post[] = [];
user: User;
post: Post;
constructor(private userService: UserService) {
this.user = this.userService.user;
}
public ngOnInit() {
this.userService.getUserFeed(this.user.id).subscribe((feed) => {
this.posts = feed;
console.log(this.posts);
});
}
}
我的组件 HTML 应该循环这些帖子并将帖子传递给我拥有的子组件
<div *ngIf="posts.length">
<mat-list *ngFor="let post of posts">
<!-- Post Display -->
<app-post-display [post]=post></app-post-display>
<!-- Post Interaction Row -->
<app-post-interaction-bar [post]=post></app-post-interaction-bar>
<!-- Comment Preview -->
<app-comment-preview [post]=post></app-comment-preview>
<mat-divider></mat-divider>
</mat-list>
</div>
到目前为止,它似乎正在按预期获取主要组件的帖子。问题出在子组件 app-post-display
中,它执行类似的操作,从 post.authorId
属性获取帖子作者。
我已经声明了一个作者,并且已经在 ngOnInit 中放置了获取作者数据的代码,但我始终在控制台中收到 ERROR TypeError: Cannot read property 'id' of undefined
,没有无论我尝试什么,组件似乎都试图在获取作者之前显示。
我需要调整什么才能在加载组件显示之前获取作者数据
import { Component, Input, OnInit } from '@angular/core';
import { UserService } from '../user/user.service';
import { User } from '../user';
import { Post } from '../post';
import { Profile } from '../profile';
import { ApiService } from '../api/api.service';
@Component({
selector: 'app-post-display',
templateUrl: './post-display.component.html',
styleUrls: ['./post-display.component.css'],
})
export class PostDisplayComponent implements OnInit {
@Input() post: Post;
user: User;
author: Profile;
constructor(private userService: UserService, private backend: BackendService) {
this.user = this.userService.user;
}
ngOnInit() {
this.backend.getProfile(this.post.authorId).subscribe((profile) => {
this.author = profile;
console.log(this.author);
});
}
}
最佳答案
子组件的
ngOnInit
只会运行一次。另外,您不能指望它获得最初定义的 post
。
要修复此问题,您应该将调用移至 ngOnChanges
并首先检查 post
是否已定义。在这里,尝试一下:
import { Component, Input, OnChanges } from '@angular/core';
import { UserService } from '../user/user.service';
import { User } from '../user';
import { Post } from '../post';
import { Profile } from '../profile';
import { ApiService } from '../api/api.service';
@Component({
selector: 'app-post-display',
templateUrl: './post-display.component.html',
styleUrls: ['./post-display.component.css'],
})
export class PostDisplayComponent implements OnChanges {
@Input() post: Post;
user: User;
author: Profile;
constructor(
private userService: UserService,
private backend: BackendService
) {
this.user = this.userService.user;
}
ngOnChanges() {
if (this.post) {
this.backend.getProfile(this.post.authorId).subscribe((profile) => {
this.author = profile;
console.log(this.author);
});
}
}
}
或者,您可以在父组件中执行此操作:
<div *ngIf="posts">
<mat-list *ngFor="let post of posts">
<!-- Post Display -->
<app-post-display [post]=post></app-post-display>
<!-- Post Interaction Row -->
<app-post-interaction-bar [post]=post></app-post-interaction-bar>
<!-- Comment Preview -->
<app-comment-preview [post]=post></app-comment-preview>
<mat-divider></mat-divider>
</mat-list>
</div>
只要确保您最初没有使用空数组初始化 posts
即可。
关于javascript - ngOnInit() 中的 Angular 8 Http Observables,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57132499/