Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/29.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在Angular中异步http调用后数据消失_Javascript_Angular_Typescript_Asynchronous_Async Await - Fatal编程技术网

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

Javascript 在Angular中异步http调用后数据消失,javascript,angular,typescript,asynchronous,async-await,Javascript,Angular,Typescript,Asynchronous,Async Await,我必须编写一个显示多个数据的树组件,它可以很好地处理模拟数据。这里的问题是,当我试图从服务器获取数据时,让我解释一下: 我有三个主要目标:地区、建筑物和门。正如您可能猜到的,doors指的是buildingId,buildingId指的是地区。因此,为了检索数据并创建树节点,我必须在forEach循环中执行一些非异步的http调用 我不会与您分享所有内容,只会将问题最小化,以便我可以轻松获得帮助: 此方法从服务器检索区域数组并将其放入本地数组中: async getDistricts(){

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

我有三个主要目标:地区、建筑物和门。正如您可能猜到的,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/wait有关。有人能帮忙吗

编辑1:尝试使用此.getDistricts().finally()代替此.getDistricts().then(),但无效

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


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

那么,您应该从
getDistricts
返回您的
承诺。此外,您的工程设计过于复杂,使
async/await
概念复杂化。我知道您不想使用
可观察对象
,但我建议您无论如何都要使用它们

通过Promissions和
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);
  }
}

那么,您应该从
getDistricts
返回您的
承诺。此外,您的工程设计过于复杂,使
async/await
概念复杂化。我知道您不想使用
可观察对象
,但我建议您无论如何都要使用它们

通过Promissions和
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);
  }
}

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

以下是我的最终代码:

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();
   }
 })
async ngOnInit():Promise{
等待此消息。districtDataService.getDistrictData().toPromise()。然后(响应=>{
this.districts=response.results为District[];
console.log(this.districts);
}).finally(异步()=>{
适用于(本区域的施工区){
等待这个.districtDataService.getBuildingsOfDistrict(district.id).toPromise()。然后(响应=>{
this.buildings=response.results为Building[];
console.log(此为建筑物);
}).finally(异步()=>{
适用于(本工程施工建筑){
等待这个.districtDataService.getDoorsOfBuilding(building.id).toPromise()。然后(响应=>{
this.doors=response.results作为Door[];
console.log(这个是doors);
}).finally(异步()=>{
用于(本工程的施工门。门){
等待这个.doorNodes.push(newdistrictNodeImpl(false,null,null,door,null));
}
})
等待this.buildingNodes.push(newdistrictNodeImpl(false,null,building,null,this.doorNodes));
}
})
等待this.dataSource.push(newdistrictNodeImpl(false,district,null,null,this.buildingNodes));
console.log(this.dataSource);
this.buildingNodes=新数组();
this.doorNodes=新数组();
}
})

希望这会有所帮助!祝你有一个愉快的一天。

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

以下是我的最终代码:

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();
   }
 })
async ngOnInit():Promise{
等待此消息。districtDataService.getDistrictData().toPromise()。然后(响应=>{
this.districts=response.results为District[];
console.log(this.districts);
}).finally(异步()=>{
适用于(本区域的施工区){
等待这个.districtDataService.getBuildingsOfDistrict(district.id).toPromise()。然后(响应=>{
this.buildings=response.results为Building[];
console.log(此为建筑物);
}).finally(异步()=>{
适用于(本工程施工建筑){
等待这个.districtDataService.getDoorsOfBuilding(building.id).toPromise()。然后(响应=>{
this.doors=response.results作为Door[];
console.log(这个是doors);
}).finally(异步()=>{
用于(本工程的施工门。门){
等待这个.doorNodes.push(newdistrictNodeImpl(false,null,null,door,null));
}
})
等待this.buildingNodes.push(newdistrictNodeImpl(false,null,building,null,this.doorNodes));
}
})
等待this.dataSource.push(newdistrictNodeImpl(false,district,null,null,this.buildingNodes));
console.log(this.dataSource);
this.buildingNodes=新数组();
this.doorNodes=新数组();
}
})

希望这会有帮助!祝你度过愉快的一天。

在你等待
编辑
地区后,尝试在
获取地区
中添加一条log语句。结果
,并记录
这个地区
。此外,如果你坚持
rxjs
,那么这整件事会更容易阅读。它仍然不起作用