开发者问题收集

Angular - 错误 TypeError:无法读取属性

2020-10-20
945

我尝试从服务器获取数据(JSON)并仅在单击按钮后显示在网络上。 第一次单击后,我收到错误:

core.js:4352 ERROR TypeError: Cannot read property 'imie' of undefined
    at HttpTestComponent.get (http-test.component.ts:28)
    at HttpTestComponent_Template_button_click_6_listener (http-test.component.html:6)
    at executeListenerWithErrorHandling (core.js:15214)
    at wrapListenerIn_markDirtyAndPreventDefault (core.js:15249)
    at HTMLButtonElement.<anonymous> (platform-browser.js:582)
    at ZoneDelegate.invokeTask (zone-evergreen.js:399)
    at Object.onInvokeTask (core.js:27474)
    at ZoneDelegate.invokeTask (zone-evergreen.js:398)
    at Zone.runTask (zone-evergreen.js:167)
    at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:480)

第二次单击后,它起作用了。问题出在哪里?

服务文件

export class LoginService {
      private url = 'http://localhost:8080/test';
      constructor(private http:HttpClient) {
      }
          getTest(): Observable<IPerson>{
    
        return this.http.get<IPerson>(this.url);
        
      }
    }

组件文件

export class HttpTestComponent implements OnInit{

  private record:IPerson;
  name: string="aaaa";
  surname: string="bbbb";
  constructor(private loginService: LoginService) { }

  get(){
       this.loginService.getTest().subscribe((data:IPerson)=>this.record = data);
        this.name = this.record.imie;
        this.surname = this.record.nazwisko;
  }
  ngOnInit(): void {
  }

}

IPerson 类

export class IPerson implements Person{

  _imie: string;
  _nazwisko: string;

  get imie(): string {
    return this._imie;
  }

  get nazwisko(): string {
    return this._nazwisko;
  }
}

模板

<p>http-test works!</p>

<h1>{{name}}</h1>
<h1>{{surname}}</h1>

<button class="btn-large" (click)="get()">Dane</button>
2个回答

这是因为 getTest() 是异步的,您需要在订阅者内部获取 props,否则记录未定义

get(){
 this.loginService.getTest().subscribe((data:IPerson)=> {
  this.record = data;
  this.name = this.record.imie;
  this.surname = this.record.nazwisko;
 });
}
Timothy
2020-10-20

问题出在这行;

this.loginService.getTest().subscribe((data:IPerson)=>this.record = data);

现在, .subscribe Observable 类型的方法,并在此引用;

Observable 是声明性的 - 也就是说,您定义了一个用于发布值的函数, 但它不会执行,直到 消费者订阅它。订阅的消费者随后会收到通知,直到函数完成或他们取消订阅。

根据您的代码,似乎您的 Observable 是对 user 执行 http GET 请求。 现在,转到下一行;

this.name = this.record.imie;

这是引发错误的代码,因为当执行此行时, this.record 仍然是 undefined ,因为您在可观察的回调中分配了 this.record

其中一种方法是在可观察的运行回调后包装代码;

this.loginService.getTest().subscribe((data:IPerson) => 
    this.record = data;
    this.name = this.record.imie;
    this.surname = this.record.nazwisko;
);

另一种方法是根据您的代码使用 async/await 封装您的函数 - 可能它会像(以下代码未经测试);

// In your service
getTest() : Promise<any> {
   const response = this.http.get(this.url).toPromise();
   return response.json(); // Not sure if this is needed.
}

// Component
async getUser() {
   const record = await this.loginService.getTest();
   this.name = record.imie;
   this.surname = record.nazwisko;
}
choz
2020-10-20