问题描述
我正在从组件中调用http Get服务方法,目的是将响应映射回组件中的Person对象以显示在前端。
我的组件:
export class displayPersonComponent implements OnInit {
personId: number;
person: Person;
constructor(private route: ActivatedRoute,private service : PersonService) { }
ngOnInit() {
this.route.params.subscribe(params => {
this.personId = params['person-id']});
this.getPerson(this.personId);
}
getPerson(id: number)
{
this.service.getPerson(id).subscribe((data: Person) => { console.log(data);
this.person = data
});
}
}
我的服务方法:
getPerson(personId : number): Observable<Person> {
let urlParams = new HttpParams().set("personId",personId.toString());
return this.http.get<Person>(this.apiUrl,{ params: urlParams})
.pipe(map((data: Person ) => { return data }),catchError(error => { return throwError(' Something went wrong! ');
})
);
}
}
当返回时,我可以检查组件中的数据对象,它看起来像json即 {PersonID:1,名称:“名称”}等 但是this.Person始终是未定义的,没有输出/错误可以解释原因。 值得一提的是,我对POST方法使用了相同的对象,并且工作正常,并且可以从客户端到服务器完美映射,而无需任何指定的映射。
解决方法
变量this.personId
是异步分配的。因此,在调用getPerson()
时,它仍未定义。
您可以使用{x {1}}之类的RxJS高阶映射运算符,而不是嵌套订阅,来从一个可观察对象映射到另一个。
switchMap
选项2:ngOnInit() {
this.route.params.pipe(
switchMap(params => this.service.getPerson(params['person-id']))
).subscribe((data: Person) => {
console.log(data);
this.person = data;
})
}
管道
如果您未在控制器中使用async
,则可以在那里跳过订阅,而在模板中使用this.person
管道
控制器
async
模板
import { Observable } from 'rxjs';
export class DisplayPersonComponent implements OnInit {
person$: Observable<Person>; // <-- type `Observable`
constructor(private route: ActivatedRoute,private service : PersonService) { }
ngOnInit() {
this.person$ = this.route.params.pipe(
switchMap(params => this.service.getPerson(params['person-id']))
);
}
}
更新:<ng-container *ngIf="(person$ | async) as person">
{{ person }}
<some-comp [person]="person">...</some-comp>
</ng-container>
引发错误,因为在订阅中为Cannot read property
变量分配了一个值之前,该变量是未定义的。使用person
的第二个选项应该可以缓解此问题。无论如何,您都可以使用安全的导航运算符async
来检查变量是否已定义,然后再尝试访问其属性。
?.
您可以了解有关异步数据here的更多信息。
,可观察对象是(x1 < x2) * 2 - 1
,在您评估async
时,尚未调用可观察对象完成时调用的内部订阅方法。
我不知道您在哪里使用person
对象,但似乎您需要重新考虑一下逻辑。
幸运的是,angular具有异步管道,可以与* ngIf一起使用:
person
此管道接收一个可观察的对象,并将其“解析”为html模板中的person对象。它也仅在此请求完成后呈现其中的内容,因此您可以在内部自由使用对象的属性!
来源和更多信息: https://ultimatecourses.com/blog/angular-ngif-async-pipe
,您的服务方法返回一个可观察值,而不是直接返回该人。 因此,如果您在可观察对象实际返回对象之前检查人员对象,则它将是未定义的。 这不是错误,而只是异步代码的工作方式。
在标记中,只需确保在呈现对象之前检查该对象是否未定义:
<div *ngIf="person">...</div>
您的POST方法起作用的原因是,您实际上可能没有对响应做任何事情。例如,如果要执行诸如在POST成功时显示敬酒通知之类的操作,则将应用相同的原理,则必须观察POST响应并对成功/错误进行操作。