【问题标题】:Data disappearing after async http calls in AngularAngular中异步http调用后数据消失
【发布时间】:2020-11-25 11:10:58
【问题描述】:

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

我有三个主要对象:区域、建筑物和门。正如您可能猜到的,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”中。并在我放入第一个方法后将数据记录到返回一个包含我的数据的数组。我想这与我使用的 async/await 有关。有人可以帮忙吗?

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

编辑 2:getDistrict 中的 console.log 在我的循环之前的那个之后执行。预期的行为会适得其反。

已解决:在我的 HTTP 调用解决此问题后,将 for 循环放入 finally 块中。所以正如答案所说,我认为我已经过度设计了 async/await 调用。我必须在此基础上重新思考我的工作。谢谢大家!

【问题讨论】:

  • 尝试在awaited districts.results 和日志this.districts 之后将日志语句放入getDistricts。此外,恕我直言,如果您坚持使用rxjs,这整件事会更容易阅读。
  • 还是不行。我尝试放置两个console.log(一个在getDistricts 中,另一个在我的for 循环之前)。实际上,forloop 中的那个在 getDistrict 中的那个之前被执行。我认为这是问题
  • 在 forEach 循环中进行一些非异步的 http 调用 - 多个 HTTP 调用如何同步? HTTP 调用在行为上始终是异步的。
  • 当有很多它们时,执行顺序很难正确。至少在我的情况下:/
  • @AymaneELJahrani:你关心执行顺序吗?

标签: javascript angular typescript asynchronous async-await


【解决方案1】:

好吧,您应该从getDistricts 退回您的Promise。此外,您对 async/await 概念的工程化和复杂化非常过度。我知道你不想使用Observables,但我还是建议你使用它们。

有了 Promise 和 async/await,你就知道如何使用它们了:

async getDistricts(): Promise<District[]> {
  const { results } = await this.districtDataService.getDistrictData();
  
  return results;
}

async ngOnInit(): Promise<void> {
  this.districts = await this.getDistricts();

  for (const district of this.districts){
    console.log(district);
  }
}

Observable 看起来像这样:

getDistricts(): Observable<District[]> {
  return this.districtDataService.getDistrictData().pipe(
    map(({ results }) => results as District[])
  );
}

ngOnInit(): void {
  this.getDistricts().subscribe((districts) => {
    this.districts = districts;
   
    for (const district of this.districts){
      console.log(district);
    } 
  });
}

【讨论】:

    【解决方案2】:

    只是为需要按所需顺序进行多次 http 调用的人提供。 正如其他人所提到的,我使异步等待的概念过于复杂。 诀窍是使用可观察对象,使用 .toPromise() 将它们转换为 Promise,使用 .then() 将数据获取到我的变量中,然后使用 .finally(async () => { ... })。

    这是我的最终代码:

    async ngOnInit(): Promise<void> {
     await this.districtDataService.getDistrictData().toPromise().then(response => {
       this.districts = response.results as District[];
       console.log(this.districts);
     }).finally(async () => {
       for (const district of this.districts){
          await this.districtDataService.getBuildingsOfDistrict(district.id).toPromise().then(response => {
          this.buildings = response.results as Building[];
          console.log(this.buildings);
         }).finally(async ()=> {
            for(const building of this.buildings){
              await this.districtDataService.getDoorsOfBuilding(building.id).toPromise().then(response => {
                this.doors = response.results as Door[];
                console.log(this.doors);
              }).finally(async () => {
                  for(const door of this.doors){
                      await this.doorNodes.push(new districtNodeImpl(false,null,null,door,null));
                  }
              })
             await this.buildingNodes.push(new districtNodeImpl(false,null,building,null,this.doorNodes));
            }
         })
         await this.dataSource.push(new districtNodeImpl(false,district,null,null,this.buildingNodes));
         console.log(this.dataSource);
         this.buildingNodes = new Array();
         this.doorNodes = new Array();
       }
     })
    

    希望这会有所帮助!祝你有美好的一天。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-25
      • 1970-01-01
      • 2018-04-24
      相关资源
      最近更新 更多