2017-04-23 37 views
2

有一個函數首先獲取環境中的所有區域,然後當他爲每個區域找到這些區域時,它將爲邊界點執行api調用。 所有取得到執行,但問題是,在然後的第一次提取,如果我嘗試寫出來的區域的長度或嘗試做一個.foreach我得到0react ajax:多重嵌套抓取獲取

我知道這是因爲它運行異步並且它在我執行console.log的那一刻還沒有加載,但是我應該這樣做。這就是爲什麼我們使用,那麼不是嗎?等待數據加載完畢。

要明確:我正在尋找一種方法,使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); 
     }); 
    }); 
    } 

已爲快速一個大感謝陣營離子和幫助。

+0

我覺得你錯誤地使用異步方法。但仍然回答這個問題,你的'zones.length'是'0',因爲它是一個我相信的'對象'。你爲什麼不嘗試'Object.keys(zones).length'而不是'zones.length'並且看看你是否有輸出? – Panther

+0

@Panther我不能這樣做,因爲當日志被執行時,區域還沒有加載。我會得到一個「無法讀取未定義的屬性」,這是完整的問題。 我第一次接受* .then *會確保一切都會被加載,但我真的不知道我做錯了什麼。 – Roel

回答

0

fetch的調用返回Promise,即async。所以你的第二個.then在連第一個裏面的代碼都執行完之前就執行完了,因爲,你的第一個然後contains另一個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. 
        }); 
       }); 
       }); 
      }) 
     } 
+0

Jup它的工作,非常非常感謝你。它看起來不漂亮,但...;) – Roel

1

在我固定它以更華麗的方式結束:

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