在 Angular 中异步 http 调用后数据消失

我必须编写一个显示多个数据的树组件,这对我来说可以很好地处理模拟数据。这里的问题是当我尝试从服务器获取数据时,让我解释一下:


我有三个主要对象:区域、建筑物和门。正如您可能猜到的,doors 指的是 buildingId,而 buildingID 指的是地区。因此,要检索数据并创建我的树节点,我必须在非异步的 forEach 循环中执行一些 http 调用。


我不会与您分享所有内容,只会分享一个最小化的问题,以便我可以轻松获得帮助:


此方法从服务器检索区域数组并将其放入本地数组中:


async getDistricts(){

   this.districtDataService.getDistrictData().toPromise().then(async districts => {

     this.districts = await districts.results as District[];

   });

}


在我的 ngOnInit 上:


ngOnInit() {

this.getDistricts().then(async () => {

  console.log(this.districts);

  for (const district of this.districts){

    console.log(district);

  }

})

第一个 console.log(在 NgOnInit 中)返回一个空数组,这很令人惊讶,因为第一个方法将数据放在“this.districts”中。并在我将其放入后立即在第一种方法中记录数据返回一个包含我的数据的数组。我想这与我使用的异步/等待有关。谁能帮忙?


编辑 1:尝试使用 this.getDistricts().finally() 而不是 this.getDistricts().then(),但没有用。


编辑 2:getDistrict 中的 console.log 在我的循环之前执行。预期的行为恰恰相反。


已解决:在我的 HTTP 调用解决此问题后,将 for 循环放入 finally 块中。所以正如答案所说,我认为我过度设计了异步/等待调用。基于此,我不得不重新思考我的工作。谢谢大家!


慕莱坞森
浏览 105回答 2
2回答

慕村225694

好吧,你应该把你的Promisefrom还给你getDistricts。此外,您过度设计并使async/await概念复杂化。我知道你不想使用Observables,但我还是建议你使用它们。有了 promises,async/await你就会明白如何使用它们:async getDistricts(): Promise<District[]> {&nbsp; const { results } = await this.districtDataService.getDistrictData();&nbsp;&nbsp;&nbsp; return results;}async ngOnInit(): Promise<void> {&nbsp; this.districts = await this.getDistricts();&nbsp; for (const district of this.districts){&nbsp; &nbsp; console.log(district);&nbsp; }}它Observable看起来像这样:getDistricts(): Observable<District[]> {&nbsp; return this.districtDataService.getDistrictData().pipe(&nbsp; &nbsp; map(({ results }) => results as District[])&nbsp; );}ngOnInit(): void {&nbsp; this.getDistricts().subscribe((districts) => {&nbsp; &nbsp; this.districts = districts;&nbsp; &nbsp;&nbsp; &nbsp; for (const district of this.districts){&nbsp; &nbsp; &nbsp; console.log(district);&nbsp; &nbsp; }&nbsp;&nbsp; });}

拉莫斯之舞

只是为了提供任何需要按所需顺序进行多个 http 调用的人。正如其他人所提到的,我将异步等待的概念过于复杂化了。诀窍是使用可观察对象,使用 .toPromise() 将它们转换为 Promises,使用 .then() 将数据放入我的变量中,然后使用 .finally(async () => { ... }).这是我的最终代码:async ngOnInit(): Promise<void> {&nbsp;await this.districtDataService.getDistrictData().toPromise().then(response => {&nbsp; &nbsp;this.districts = response.results as District[];&nbsp; &nbsp;console.log(this.districts);&nbsp;}).finally(async () => {&nbsp; &nbsp;for (const district of this.districts){&nbsp; &nbsp; &nbsp; await this.districtDataService.getBuildingsOfDistrict(district.id).toPromise().then(response => {&nbsp; &nbsp; &nbsp; this.buildings = response.results as Building[];&nbsp; &nbsp; &nbsp; console.log(this.buildings);&nbsp; &nbsp; &nbsp;}).finally(async ()=> {&nbsp; &nbsp; &nbsp; &nbsp; for(const building of this.buildings){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await this.districtDataService.getDoorsOfBuilding(building.id).toPromise().then(response => {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.doors = response.results as Door[];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log(this.doors);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }).finally(async () => {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for(const door of this.doors){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await this.doorNodes.push(new districtNodeImpl(false,null,null,door,null));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; })&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;await this.buildingNodes.push(new districtNodeImpl(false,null,building,null,this.doorNodes));&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp;})&nbsp; &nbsp; &nbsp;await this.dataSource.push(new districtNodeImpl(false,district,null,null,this.buildingNodes));&nbsp; &nbsp; &nbsp;console.log(this.dataSource);&nbsp; &nbsp; &nbsp;this.buildingNodes = new Array();&nbsp; &nbsp; &nbsp;this.doorNodes = new Array();&nbsp; &nbsp;}&nbsp;})希望这会有所帮助!祝你今天过得愉快。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript