Angular Async函数OnInit

问题描述 投票:0回答:1

希望你有一个美好的一天。我在处理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()合并到一个按钮中,但这不是我的真正意图。我以前也遇到过这个问题,我很想妥善解决。所以问题是,我如何等待它的完成,以便运行下一个函数。

任何帮助都将是感激不尽的!👤"。

angularjs typescript asynchronous httprequest
1个回答
1
投票

一种方法是将 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)
    }


1
投票

@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
        });

希望对你有帮助。


1
投票

如你所见,你的问题有几种不同的解决方案。我的建议是继续使用可观察链,等到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数组转换为一个对象,以便更容易和更快地检查重复的信息。

编码快乐!

© www.soinside.com 2019 - 2024. All rights reserved.