我有一个接收服务返回的可观察对象的函数。我需要此函数来迭代Observable发出的数据,并根据接收到的数据构造一个数组。
我可以理解如何以所需的方式构造数组,但是我不明白的是如何返回数组。
getTop5Crypto() : string[] {
let top5CryptoIds : string[] = [];
this.cryptoService.getCryptoMarkets().subscribe(res => {
let data = res.data;
for(let i = 0; i < 5; i++) {
top5CryptoIds.push(data[i].baseId)
}
});
return top5CryptoIds; //<-- Will return empty array
}
在上面的函数中,我构造了数组,然后返回它。但是,由于return命令在异步代码之外,因此它将在异步代码之前执行,这意味着该函数将返回一个空数组。
如果我将返回值放在next
可观察函数的内部,使其位于异步代码内部,则编译器将给出错误,因为并非函数中的所有路径都将返回值。如果我在异步代码中有两个返回命令,一个在内部,一个在外部,那么我们又回到了第一个问题。
更新:全班学习
export class HomeComponent implements OnInit {
//cryptos: string[] = ['bitcoin', 'ethereum', 'litecoin']
cryptoDetails: CryptoDetail[];
constructor(private cryptoService: CryptoService) { }
ngOnInit() {
this.cryptoDetails = new Array();
let ids : string[] = this.getTop5Crypto();
this.getCryptoData(ids);
const source = interval(5000).subscribe(val => this.getCryptoData(ids))
}
getCryptoData(ids: string[]){
this.cryptoDetails = [];
console.log("get crypto")
for(let crypto of ids){
this.cryptoService.getCryptoInfo(crypto).subscribe(res => {
let data = res.data;
let cryptoDetail = new CryptoDetail(data.id, data.rateUsd, data.symbol);
this.cryptoDetails.push(cryptoDetail);
})
}
}
async getTop5Crypto() : Promise<string[]> {
let top5CryptoIds : string[] = [];
await this.cryptoService.getCryptoMarkets().subscribe(res => {
let data = res.data;
for(let i = 0; i < 6; i++) {
top5CryptoIds.push(data[i].baseId)
}
});
return top5CryptoIds;
}
答案 0 :(得分:1)
您可以使用switchMap()
使用from()
来发射每个数组项,然后映射到baseId
来发射ID。如果要限制发射的数量,请使用take(5)
,最后使用toArray()
将所有值作为数组发射。
getTop5Crypto() : Observable<string[]> {
return this.cryptoService.getCryptoMarkets().pipe(
switchMap(res => from(res.data)),
map(data => data.baseId),
take(5),
toArray()
);
}
答案 1 :(得分:-1)
为此,您不应该订阅可观察的对象,可以返回带值的可观察对象或使用async / await,使用toPromise()将您的可观察对象转换为Promise。
在您的情况下,您返回的值在返回时无法解析
async getTop5Crypto() : Promise<string[]> {
let top5CryptoIds : string[] = [];
let top5CryptoIds = await this.cryptoService.getCryptoMarkets()
.pipe(
switchMap(res => {
let data = res.data;
for(let i = 0; i < 5; i++) {
top5CryptoIds.push(data[i].baseId)
}
});
).toPromise()
retrun top5CryptoIds
}
答案 2 :(得分:-1)
通常,最佳做法是返回一个可观察的数据而不是内部数据。
如果您仍然想读取该值,则可以使用take(1)
进行“一次性读取”:
getTop5Crypto() : string[] {
let top5CryptoIds : string[] = [];
this.cryptoService.getCryptoMarkets().pipe(take(1)).subscribe(res => {
let data = res.data;
for(let i = 0; i < 5; i++) {
top5CryptoIds.push(data[i].baseId)
}
});
return top5CryptoIds;
}
当您只对第一个发射感兴趣时,您想使用 采取。也许您想看看用户在他们第一次点击时 进入页面,或者您想订阅点击事件 并进行第一次发射。另一个用例是当您需要 在特定时间点拍摄数据快照,但不要 需要进一步的排放。例如,用户令牌流 更新,或基于Angular应用程序中的流的路由防护。