javascript - 如何使用 foreach 循环在其他异步调用中进行异步调用
问题描述
我真的很想改进并了解如何更好地做到这一点。这段代码有效,但我相信这里有问题。思路如下:
1:我对 API 进行了第一次 HTTP 调用并获得了数据。
2:我使用的数据是 matchHistoryArr ,它有一个包含 10 个“gameIds”的数组,我需要将它们通过 forEach(loop) 传递给 this.summ.getMatches(gameId) 并将它们推送到需要比较的新本地数组另一个数组对其进行排序(因为异步没有对其进行排序)所以在搜索了很多之后我可以像这样解决它。(我将在代码中标记) 注意:这是我遇到大问题的地方,
3:现在我需要从其他端点获取更多数据,但我相信在继续之前我必须更好地订购代码。
组件.ts
onSubmit(){
** 1 **
this.summ.getSummoner(this.summoner.name,this.summoner.regionId)
.subscribe( (data:any) => {
let matchHistoryArr = data.matchHistory
let gameIdArray = matchHistoryArr.map( element => element.gameId)
const subscribers: Subscriber<any>[] = [];
const promiseMatchesArray = [];
** 2 **
matchHistoryArr.forEach( element => {
promiseMatchesArray.push( this.summ.getMatches(element.gameId).toPromise().then( match => {
subscribers.push(match)
}));
});
Promise.all(promiseMatchesArray).then( a =>{
if ( subscribers.length === matchHistoryArr.length ){
let arraySort = [];
arraySort = subscribers
let dataParticipants
let matchesArraySorted = arraySort.sort((a, b) => {
return gameIdArray.indexOf(a.gameId) - gameIdArray.indexOf(b.gameId);
});
this.matchesArray = matchesArraySorted
matchesArraySorted.forEach( x => {
dataParticipants = x.participants
});
if ( dataParticipants.length === 10 ){
this.dataParticipants = dataParticipants
}
}
});
this.matchHistory = matchHistoryArr
this.SummInfo = data.summonerdata;
});
}
服务.ts
export class SummonerService {
constructor( private http:HttpClient ) { }
summonerName
getSummoner(summonerName,regionId){
this.summonerName = summonerName
return this.http.get(`http://localhost:3000/summName/${summonerName}/${regionId}` )
.pipe(
map( (data:any) => data)
)};
getChampImage(champId){
return this.http.get(`https://raw.communitydragon.org/latest/plugins/rcp-be-lol-game-data/global/default/v1/champion-icons/${champId}.png`)
};
getMatches(gameId){
return this.http.get( `http://localhost:3000/match/${gameId}` )
.pipe(
map( (data:any) => this.uploadData(data))
)};
解决方案
本质上,您的示例可以归结为两个步骤:
- 从 observable 中获取数据
- 根据来自 1 的数据执行一组调用。
我建议始终坚持使用 observables,除非有令人信服的理由使用 Promise。
- 在执行 1a 时进行初始呼叫。使用切换到新的 observable
concatMap
- 创建 observables 数组并使用并行运行
forkJoin
onSubmit() {
this.summ.getSummoner(this.summoner.name, this.summoner.regionId)
.pipe(
tap((summoner) => this.matchHistory = summoner.matchHistory),
concatMap((summoner: any) => {
const observables = this.matchHistory
.map(element => this.summ.getMatches(element.gameId));
return forkJoin(observables)
}),
map(matchesArray => {
// TODO: perform sorting
return matchesArray;
})
).subscribe(matchesArray => {
});
}
我省略了您的排序以保持答案简单。
matchesArray
是反映输入的结果数组observables
。
您想要执行的任何排序都可以在map
运算符中执行。
您想要保存在管道之外的任何状态都可以在tap
操作员中完成。
组合 observables 的关键是记住只有一个顶级订阅者。Observables 几乎可以用任何你能想到的使用管道操作符的方式组合起来。这就是为什么我建议坚持使用 observables。在复杂场景中,它们比 Promise 更强大。
推荐阅读
- javascript - 如何在另一个组件上运行 React Native 生命周期
- java - 单击时 RadioGroup 失败
- android - 旋转布局的背景图像
- javascript - 未定义单击时的功能
- c# - 具有多个 HttpPost 方法的 Web Api 中的 CORS 问题
- php - PHP 脚本 - 如何在我的脚本中使用 php artisan 命令?
- sql - Redshift:范围连接的 DIST KEY 和 SORT KEY 策略
- angular - Angular Material进度微调器在线
- reactjs - 如何在 React Semantic UI 中使用 List 组件“items”道具?
- c - 我们如何在#define 语句中使用联合和结构