3 votes

react ajax : multiple nested fetch Get

Il y a une fonction qui récupère d'abord toutes les zones d'un environnement, puis, lorsqu'elle a trouvé ces zones, pour chaque zone, elle fait un appel à l'API pour les points limites. Toutes les requêtes sont exécutées, mais le problème est que dans la fonction puis pour la première recherche si j'essaie d'écrire le nom de l'utilisateur. longueur des zones ou essayer de faire un .foreach Je reçois 0.

Je sais que c'est parce qu'il fonctionne en asynchrone et qu'il n'est pas encore chargé au moment où je fais le console.log, mais je pensais qu'il devrait l'être. C'est pourquoi nous utilisons la fonction .alors n'est-ce pas ? d'attendre que les données soient chargées.

Pour être clair : Je cherche un moyen pour que zones.length renvoie la longueur réelle du tableau d'objets et soit évalué immédiatement au lieu de 0. Je ne trouve pas comment :

Voici le code.

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

Déjà un grand merci pour la rapidité React et de l'aide.

1voto

Roel Points 30

A la fin, je l'ai arrangé d'une manière plus belle :

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

0voto

Panther Points 4678

Les appels à fetch renvoie un Promise et c'est async . Donc votre deuxième .then s'exécute avant même que le code dans le premier then ne soit terminé car, votre premier then contains un autre fetch qui est appelée et qui est asynchrone. Vous pouvez avoir une logique comme ci-dessous pour attendre jusqu'à ce que vous obteniez tous les points de données et ensuite procéder avec votre logique.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X