首页 > 解决方案 > 无法将从 http Get 返回的数据分配给具有相同结构的打字稿对象

问题描述

我正在从组件调用 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, Name: 'Name'} 等 但是 this.Person 始终未定义,并且没有输出/错误来解释原因。还值得一提的是,我对 POST 方法使用了相同的对象,它工作正常,并且可以完美地从客户端映射到服务器,而无需任何指定的映射。

标签: angulartypescriptrxjsangular-httpclientangular2-observables

解决方案


变量this.personId是异步分配的。所以在getPerson()被调用的时候,它仍然是未定义的。

您可以使用 RxJS 高阶映射运算符代替嵌套订阅,例如switchMap从一个 observable 映射到另一个。

ngOnInit() {
  this.route.params.pipe(
    switchMap(params => this.service.getPerson(params['person-id']))
  ).subscribe((data: Person) => {
    console.log(data);
    this.person = data;
  })
}

选项2: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应该可以缓解这个问题。在任何情况下,您都可以使用安全导航运算符?.来检查变量是否已定义,然后再尝试访问它的属性。

<div>
  {{ person?.personId }}
  {{ person?.someProp }}
  {{ person?.someOtherProp }}
</div>

您可以在此处了解有关异步数据的更多信息。


推荐阅读