希望你有一个美好的一天。我在处理ngOninit()的异步调用时遇到了这个问题。基本上我需要按顺序加载一些东西,但我不知道怎么做。下面是代码。
import { Component, OnInit } from '@angular/core';
import { Match, Game, participantIdentities, player } from '../../models/match';
import { MatchService } from '../../services/match.service';
import { Global } from '../../services/global';
import { Observable } from 'rxjs';
@Component({
selector: 'app-players',
templateUrl: './players.component.html',
styleUrls: ['./players.component.css'],
providers: [MatchService]
})
export class PlayersComponent implements OnInit {
public matchs: Array<Match>;
public games: Array<Game>
public player: Array<player>;
public players: []
constructor(
private _matchService: MatchService
) {
this.games = []
this.player = []
}
ngOnInit(): void {
this.getMatchs()
}
getMatchs(){
this._matchService.getMatchs().subscribe(
response =>{
this.matchs = response.matchs;
console.log(this.matchs);
for(let i = 0; i<this.matchs.length; i++){
this.games[i] = this.matchs[i].game;
};
console.log(this.games)
}
,error=>{
console.log(<any>error)
}
);
}
getUsers(){
let accountId = [];
for(let i = 0; i < this.matchs.length; i++){
for(let x = 0; x < this.matchs[i].game.participantIdentities.length; x++){
if ( typeof(accountId.find(element=>element == this.matchs[i].game.participantIdentities[x].player.summonerName)) === "undefined"){
accountId.push(this.matchs[i].game.participantIdentities[x].player.summonerName)
this.player.push(this.matchs[i].game.participantIdentities[x].player)
}
}
}
console.log(this.player)
}
}
如你所见,getUsers()函数使用的数据来自getMatchs()。如果我在ngOninit getUsers()上同时执行这两个函数,它将抛出一个错误,因为另一个函数还没有完成。这是有道理的,当然,我可以把getMatchs()和ngOninit getUsers()结合起来。当然,我可以把getUsers()合并到一个按钮中,但这不是我的真正意图。我以前也遇到过这个问题,我很想妥善解决。所以问题是,我如何等待它的完成,以便运行下一个函数。
任何帮助都将是感激不尽的!👤"。
一种方法是将 getUsers()
紧接着 this.matchs = response.matchs;
那么每次你打电话 getMatchs
它称之为 getUsers
也是。
另一种方法是把订阅移到ngOnInit。
ngOnInit(): void {
this.getMatchs().subscribe(response => {
this.matchs = response.matchs;
for(let i = 0; i<this.matchs.length; i++){
this.games[i] = this.matchs[i].game;
};
this.getUsers();
});
}
getMatchs(){
return this._matchService.getMatchs();
}
getUsers(){
let accountId = [];
for(let i = 0; i < this.matchs.length; i++){
for(let x = 0; x < this.matchs[i].game.participantIdentities.length; x++){
if ( typeof(accountId.find(element=>element == this.matchs[i].game.participantIdentities[x].player.summonerName)) === "undefined"){
accountId.push(this.matchs[i].game.participantIdentities[x].player.summonerName)
this.player.push(this.matchs[i].game.participantIdentities[x].player)
}
}
}
console.log(this.player)
}
@satanTime的解决方案很好。然而,我想提供另一个解决方案,以防止你不想错把 getUsers()
呼叫。
你可以尝试使用 Promises
.
getMatchs(): Promise<void> {
return new Promise((resolve, reject) => {
this._matchService.getMatchs().subscribe(
response => {
// Do whatever you need
resolve();
},
error => {
// Handle error
// reject(); if you want to scale the exception one level upwards.
}
);
});
}
然后,重写你的 ngOnInit
这样的方法
ngOnInit(): void {
this.getMatchs().then(() => {
this.getUsers();
});
}
这就变得相当有可读性了。
获取 火柴. 一旦你完成,得到用户。
為了完成任務和增加樂趣,你可以把它投給我們。Observable
返回 _matchService.getMatchs()
到 Promise
,工作,然后返回。
getMatchs = (): Promise<void> =>
this._matchService.getMatchs().toPromise()
.then(response => {
// Do whatever you need
})
.catch(err => {
// Handle error
});
希望对你有帮助。
如你所见,你的问题有几种不同的解决方案。我的建议是继续使用可观察链,等到getMatchs完成。比如说,你必须改变你的getMatchs。
ngOnInit(): void {
this.getMatchs().subscribe(res => this.getUsers());
}
那么你就必须改变你的getmatchs函数,像这样。
getMatchs() {
this._matchService.getMatchs().pipe(
tap(result => {
this.matchs = response.matchs;
this.games = this.matchs.map(m => m.game);
})
);
通过这样做,你可以继续使用你的可观察流。
这应该是可行的,但还有其他问题需要你注意。其中之一是,为了避免应用程序中的内存泄漏,退订每个订阅是一个非常好的做法。您可以通过调用 unsubscribe()
手动或依靠 async
管道从angular。
https:/rxjs-dev.firebaseapp.comguidesubscription。
https:/angular.ioapicommonAsyncPipe。
另一方面,如果你能修改你的代码以减少在相同信息上的循环次数,你会得到更好的性能。看看我为你做的这个GetMatchs的其他版本(未测试),但希望能给你一个如何提高组件性能的想法。
processMatches() {
this._matchService.getMatches().pipe(
tap(response => {
this.matches = response.matchs;
let accountId = {};
this.matches.forEach((m, index) => {
this.game[index] = m[index].game;
this.game[index].participantIdentities
.forEach(p => {
if (!accountId[p.player.sumonerName]) {
accountId[p.player.sumonerName] = p.player.sumonerName;
this.player.push(p.player);
}
});
});
})
)
}
同样,这段代码没有经过测试,这里的想法是减少循环,并将accountId数组转换为一个对象,以便更容易和更快地检查重复的信息。
编码快乐!