我需要一些帮助。我有一个带有 Angular 的 amChart 世界地图,我也有一个可观察的函数,我可以在控制台中显示从 firestore 获取的值,但我无法在地图中显示。
this.countries.map((country) =>
this.chartService
.getNumberOfSuppliers(`organizations_${country.toLowerCase()}`)
.subscribe((num) => {
this.countryValue = num?.[0]?.num_org;
// -------- BUG --------------
// It Show values in console. The values is correct, but no is displaying in the worldchart
// The value which taking is the default -> 0
console.log(`${country.toLocaleUpperCase()} :`, this.countryValue); // it show the correct values
})
);
this.data = this.countries.map((country) => ({
id: country,
name: this.getCountryName(country),
value: this.countryValue[country], //Here I need show the values
}));
getNumberOfSuppliers(s: string): Observable<any> {
const chartData = collection(this.firestore, s);
return collectionData(chartData, { idField: 'id' });
}
我认为问题的出现是因为代码流处理不当 尝试以下方法
this.countries.map((country) =>
this.chartService
.getNumberOfSuppliers(`organizations_${country.toLowerCase()}`)
.subscribe((num) => {
this.countryValue = num?.[0]?.num_org;
console.log(`${country.toLocaleUpperCase()} :`, this.countryValue);
this.data = this.countries.map((country) => ({
id: country,
name: this.getCountryName(country),
value: this.countryValue[country],
}));
})
)
此处,this.data 分配将发生在订阅块内,确保在 this.data 中使用之前将正确的值分配给 this.countryValue。
尝试一下并告诉我们
您没有获得所需结果的原因是您将
Observable[]
分配给您的 this.data
,而您确实想要实际的数据形状。
首先,我们应该摆脱 .map 循环内的显式订阅,因为它们永远不会被取消订阅。您可以将发出的值“管道”到您想要的形状,而不是订阅。
private requests = this.countries.map(country => this.chartService
.getNumberOfSuppliers(`organizations_${country.toLowerCase()}`).pipe(
map(num => num?.[0]?.num_org),
map(countryValue => ({
id : country,
name : this.getCountryName(country),
value : countryValue,
}))
)
);
在这里,我们将每个国家/地区映射到一个可观察的对象中,它将发出您想要的形状(我们称之为
Data
)。所以 requests
是 Observable<Data>[]
。
我们可以使用
forkJoin
订阅可观察数组并将其结果作为数组发出。
private sub = forkJoin(requests).subscribe(
data => this.data = data // here data is Data[]
);
ngOnDestroy() {
this.sub.unsubscribe();
}
您可以将
.subscribe()
的结果保存在单独的变量中,而只需将其保持为可观察并在模板中使用 async
管道即可。这更简单,因为您不再需要处理取消订阅:
public data$ = forkJoin(requests);
<!-- This is just for displaying the data in the template-->
<pre>
{{ data$ | async | json }}
</pre>
<!-- But you'd really just pass it as an input to some component -->
<some-component [input]="data$ | async" />