[英]How do you turn an Observable array of objects, into an Observable of the data inside that array of objects?
I'm getting this error:我收到此错误:
Type 'Observable<Country[]>' is not assignable to type 'Observable'.
类型“Observable<Country[]>”不可分配给类型“Observable”。 Type 'Country[]' is missing the following properties from type 'Country': name, tld, alpha2Code, alpha3Code, and 20 more.ts(2322
类型“Country[]”缺少类型“Country”中的以下属性:name、tld、alpha2Code、alpha3Code 和 20 more.ts(2322
I think it's because the endpoint im reaching serves back an array with an object inside of it.我认为这是因为我到达的端点返回一个数组,其中包含一个对象。 Here's an example.
这是一个例子。
https://restcountries.com/v3.1/name/peru https://restcountries.com/v3.1/name/peru
This is the code I can't get to work.这是我无法开始工作的代码。 It refuses to compile and gives me the error I posted above.
它拒绝编译并给我上面发布的错误。
export class DetailsComponent implements OnInit {
country$!: Observable<Country>
countryBorders$!: Observable<Country[]>
constructor(private apiService: ApiService, private activatedRoute: ActivatedRoute){}
ngOnInit(): void {
this.activatedRoute.params.subscribe((params) => {
let countryName = params['country'];
this.country$ = this.apiService.getCountryByName(countryName)
});
};
}
The getCountryByName() method looks like this: getCountryByName() 方法如下所示:
getCountryByName(name: string) {
return this.http
.get<Country[]>(`${this.api}/name/${name}`)
}
How do I get the "this.country$" variable/observable/subject (idk what it is technically), to hold the data thats inside the object thats inside of the array that's being returned by the HTTP request?我如何获取“this.country$”变量/可观察/主题(idk 技术上是什么),以保存 HTTP 请求返回的数组内的对象内的数据?
I thought I could map the values out of the array, but this doesn't work either:我以为我可以将值映射到数组之外,但这也不起作用:
ngOnInit(): void {
this.activatedRoute.params.subscribe((params) => {
let countryName = params['country'];
this.country$ = this.apiService.getCountryByName(countryName).pipe(map(([info])=>return info)
});
};
}
When I do that, I don't get the error but this template:当我这样做时,我没有得到错误,但是这个模板:
<div *ngIf="country$ | async as country">
<h1>{{country$}}</h1>
</div>
renders渲染
[object Object]
...like the h1 on the page literally just says "[object Object]" ...就像页面上的 h1 字面意思只是说“[object Object]”
What am I doing wrong?我究竟做错了什么? What combination of operators do I need to use to convert the 'Observable<Country[]>' into just 'Observable<Country' so I can render it inside an html template like this?
我需要使用什么运算符组合来将 'Observable<Country[]>' 转换为 'Observable<Country' 以便我可以在这样的 html 模板中呈现它?
<div>
<p><strong>Native Name: </strong>{{ country$.name.nativeName }}</p>
<p><strong>Population: </strong>{{ country$.population | number : '0.0' }}</p>
<p><strong>Region: </strong>{{ country$.region }}</p>
<p><strong>Sub Region: </strong>{{ country$.subregion }}</p>
<p><strong>Capital: </strong>{{ country$.capital }}</p></div>
<div>
<p><strong>Top Level Domain: </strong>{{ country$.tld }}</p>
<p><strong>Currencies: </strong>{{ country$.currencies }}</p>
<p><strong>Languages: </strong>{{ country$.languages }}</p>
</div>
</div>
This is the interface in case it's relevant to the answer:这是与答案相关的界面:
export interface Country {
name: Name; //---
tld: string[]; //---
cca2: string;
ccn3: string;
cca3: string;
cioc: string;
independant: Boolean
status: string;
unMember: Boolean;
currencies: Currency[]; //---
idd: Idd;
capital: string[]; //---
altSpellings: string[];
region: string;
subregion: string; //---
languages: any; //---
translations: any;
latlng: number[];
landlocked: Boolean;
borders: string[]; //---
area: number;
demonyms: any;
flag: string;
maps: Maps;
population: number; //---
gini: any;
fifa: string;
car: any;
timezones: string[];
continents: string[];
flags: Flags;
coatOfArms: COA;
startOfWeek: string;
capitalInfo: Capital;
postalCode: Postal;
// nativeName: string;
// numericCode: string;
// regionalBlocs: RegionalBloc[];
}
Looks like you have a typing issue in your getCountryByName
method.看起来您的
getCountryByName
方法中存在输入问题。 Instead of .get<Country[]>
, it should be .get<Country>
:而不是
.get<Country[]>
,它应该是.get<Country>
:
getCountryByName(name: string) {
return this.http
.get<Country>(`${this.api}/name/${name}`)
}
The RestCountries API returns the response with an array type. RestCountries API 返回具有数组类型的响应。 You can achieve with extract the first element of the array via
map
rxjs.您可以通过
map
rxjs 提取数组的第一个元素来实现。
getCountryByName(name: string): Observable<Country> {
return this.http
.get<Country[]>(`${this.api}/name/${name}`)
.pipe(map((x) => x[0]));
}
The way you extract the properties from the country$
Observable is incorrect.您从
country$
Observable 中提取属性的方式不正确。 You should look for an async
pipe as what you have achieved in the question.您应该寻找一个
async
管道作为您在问题中取得的成就。
<div *ngIf="country$ | async as country">
<div>
<p><strong>Native Name: </strong>{{ country.name.nativeName | json }}</p>
<p>
<strong>Population: </strong>{{ country.population | number: '0.0' }}
</p>
<p><strong>Region: </strong>{{ country.region }}</p>
<p><strong>Sub Region: </strong>{{ country.subregion }}</p>
<p><strong>Capital: </strong>{{ country.capital }}</p>
</div>
<div>
<p><strong>Top Level Domain: </strong>{{ country.tld }}</p>
<p><strong>Currencies: </strong>{{ country.currencies }}</p>
<p><strong>Languages: </strong>{{ country.languages }}</p>
</div>
</div>
This was the correct format:这是正确的格式:
export class DetailsComponent implements OnInit {
country$!: Observable<Country>
countryBorders$!: Observable<Country[]>
constructor(private apiService: ApiService, private activatedRoute: ActivatedRoute){}
ngOnInit(): void {
this.activatedRoute.params.subscribe((params) => {
let countryName = params['country'];
this.country$ = this.apiService.getCountryByName(countryName).pipe(map(([info])=>{return info}))
});
};
}
I was doing it right.我做对了。 But in the template use:
但在模板中使用:
<div *ngIf="country$ | async as country">
<h1>{{country.name.common}}</h1>
</div>
NOT不是
<div *ngIf="country$ | async as country">
<h1>{{country$.name.common}}</h1>
</div>
dumb mistake愚蠢的错误
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.