Ionic3+Angular5调用REST API:为何无法用data.results获取数据?
data.results访问API响应,只能用data["results"]? 我首次使用Ionic 3和Angular 5,想要实现一个简单的REST API调用并将结果展示为列表。了解到需要创建负责调用的Provider,我参考示例编写了如下PeopleServiceProvider代码:
import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; //import 'rxjs/add/operator/map' /* Generated class for the PeopleServiceProvider provider. See https://angular.io/guide/dependency-injection for more info on providers and Angular DI. */ @Injectable() export class PeopleServiceProvider { dati : string constructor(public http: HttpClient) { console.log('Hello PeopleServiceProvider Provider'); } load() { if (this.dati) { // already loaded data return Promise.resolve(this.dati); } // don't have the data yet return new Promise(resolve => { // We're using Angular HTTP provider to request the data, // then on the response, it'll map the JSON data to a parsed JS object. // Next, we process the data and resolve the promise with the new data. this.http.get('https://randomuser.me/api/?results=10') //.map(res => res.json()) .subscribe(data => { // we've got back the raw data, now generate the core schedule data // and save the data for later reference console.log(data); this.dati = data["results"]; resolve(this.dati); }); }); } }
目前模板运行正常,但我有一个疑问:从API获取响应后,必须使用data["results"]才能拿到结果,原本以为可以直接使用data.results,请问我哪里遗漏了相关内容?
这其实是TypeScript类型系统在起作用的原因,我来给你拆解清楚:
HttpClient的默认返回类型限制
Angular的HttpClient.get()默认返回的是Observable<Object>类型,而Object在TypeScript的类型定义里并没有results这个属性。直接写data.results会触发类型检查错误——TypeScript不知道这个响应对象里存在results字段,所以会报错阻止你这么写;但使用方括号语法data["results"]属于JavaScript的动态属性访问,TypeScript对这种写法的类型检查会宽松很多,所以不会报错。两种解决办法,推荐第一种
办法一:给响应指定明确类型(类型安全)
你可以先定义一个接口来描述API返回的数据结构,让TypeScript清楚知道响应里有哪些字段:// 先定义接口描述返回结构 interface RandomUserResponse { results: { name: { first: string; last: string }; email: string; // 可以根据API返回的字段补充更多定义 }[]; info: { seed: string; results: number }; } // 在get请求里指定这个类型 this.http.get<RandomUserResponse>('https://randomuser.me/api/?results=10') .subscribe(data => { this.dati = data.results; // 现在就能正常使用点语法了 resolve(this.dati); });这种方式不仅解决了语法问题,还能让代码有类型保障,后续修改时不容易出错。
办法二:临时断言为any类型(快速解决)
如果不想写接口,也可以把data断言为any类型,让TypeScript跳过类型检查:.subscribe((data: any) => { this.dati = data.results; resolve(this.dati); });不过这种方式没有类型检查的保护,大型项目里不建议频繁使用。
额外小修正
你代码里的dati定义为string类型,但实际上它接收的是一个数组,建议改成对应类型:dati: typeof RandomUserResponse['results']; // 或者直接写any[]
内容的提问来源于stack exchange,提问作者user3336884

