React AJAX:多层嵌套的Fetch Get请求

5

有一个函数首先获取环境中的所有区域,然后对于每个区域,它都会调用API来获取边界点。所有获取操作都会执行,但问题是,在第一个获取的then中,如果我尝试输出区域的长度或执行.foreach操作,我得到的是0。

我知道这是因为它是异步运行的,并且在我执行console.log的时候还没有加载完成,但我认为应该已经加载完成了。这就是为什么我们使用.then,不是吗?等待数据加载完成。

明确一下:我正在寻找一种方法,使zones.length立即返回对象数组的实际长度,并立即计算,而不是返回0。我无法找到解决方法:

以下是代码。

getZones(){
      var that = this;
  var zones = new Array();
  fetch('api/environment/zone/1').then(function(response){
    response.json().then(function(data){
      data.forEach(function(element){
        zones[element.zoneID] = element;
        zones[element.zoneID].points = [];
        fetch('api/zone/point/'+element.zoneID).then(function(response){
          response.json().then(function(data){
            data.forEach(function(element){
              zones[element.zoneID].points.push(element);  
            });
          }); //closing of data inner fetch.
          });
        });
      });
    }).then(function(response){
      console.log(zones); //this gives all zones
      console.log(zones.length); //this one gives 0
//the for each is never executed because it's still 0.
      zones.forEach(function(element){  
        console.log(element);
      });
    });
  }

非常感谢您快速的反应和帮助,已经做出了很大的贡献。


我认为您错误地使用了异步方法。但是仍然回答您的问题,我相信您的zones.length是一个object,所以为0。为什么不尝试使用Object.keys(zones).length而不是zones.length,看看是否会有输出呢? - Panther
@Panther,我不能这样做,因为当该日志被执行时,区域尚未加载。我会得到一个“无法读取未定义属性”的完整问题。 我最初认为 .then 会确保一切都被加载,但我真的不知道我做错了什么。 - Roel
2个回答

2
最终,我以一种更加优美的方式解决了它:
getZones2(){
      var that = this;
      var zones = [];
  fetch('api/environment/zone/1')
    .then(res => res.json())
    .then((json) => {
      Promise.all(
        json.map(
          element => fetch('api/zone/point/' + element.zoneID)
            .then(res => res.json())
        )
      ).then(datas => {
        json.forEach((element, i) => {
          zones[element.zoneID] = element
          zones[element.zoneID].points = datas[i]

        })
        console.log(zones);
        zones.forEach(function(response){
            that.makeZone(response.name,response.zoneID,response.points);
        })
      })
    });
}

0

fetch 调用返回一个 Promise,并且是 async 的。因此,你的第二个 .then 在第一个 then 中的代码完成之前就已经执行了,因为你的第一个 then 包含另一个被调用的异步 fetch 函数。你可以使用以下逻辑等待获取所有点数据,然后继续执行你的逻辑。

    getZones(){
          var that = this;
          // var zones = new Array();

          // this function gets called finally.
          // Do what you want to do with zones and points here.
          var gotAllZones = function(zones) {

              console.log(zones); //this gives all zones
              console.log(Object.keys(zones).length); //this one gives 0

              Object.keys(zones).forEach(function(index){  
                console.log(zones[index]);
              });
          }

          fetch('api/environment/zone/1').then(function(response){
            response.json().then(function(data){
              //decleare zones to be a object. Based on your code `zones` is not an array
              var zones = {};
              var pointsDone = 0; // declare how many points api has been completed. Initially its `0`
              data.forEach(function(element){
                zones[element.zoneID] = element;
                zones[element.zoneID].points = [];
                fetch('api/zone/point/'+element.zoneID).then(function(response){
                  response.json().then(function(innerData){
                    innerData.forEach(function(element){
                      zones[element.zoneID].points.push(element);  
                    });
                    pointsDone++; //each time we are done with one. we increment the value.

                    // we check if we are done collecting all points data
                    // if so we can call the final function. 
                    if(pointsDone === data.length) {
                      gotAllZones(zones);
                    }
                  }); //closing of data inner fetch.
                  });
                });
              });
            })
      }

没错,它可以工作了,非常非常非常感谢你。虽然它看起来不是很美观,但是... ;) - Roel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接