0

What I am trying to achieve here is to build a chart with the average SLA for each of the 4 regions. For this, I am calling an API to get some ids, I use these ids to call another API and get the SLAs. Then, I'm calculating the average SLA. I have to do this 4 times for each region. In the end, I want to have 2 arrays containing the region names and the average SLAs, so I can build the chart. Problem is, I can't get the SLA data out of these nested functions, so I can build the array. It tells me that the variables are undefined.

So the question is why can't I access the average var as soon as I leave the function? I tried using return average;. I also tried returning from both function(response) and function(data). This is the first JS I write and I feel like there is something very wrong with it. Can you help me find out what?

// This is the fetch that gets me the SLAs and where I calculate the averages. 

function regionsla(serviceids, regionName) {
  fetch('api.php', {
    // request body
  }).then(
    function(response) {
      response.json().then(
        function(data) {
          var i = 0;
          var sum = 0;
          var labels = [];
          var values = [];

          for (const label in data.result) {

            sum = sum + data.result[label].sla[0].sla;
            i++;
          }

          average = sum / i;

          labels.push(regionName);
          values.push(average);
        }
      )
    }
  );
}

// This is the main function that runs in the beginning. The fetch is inside a for loop and it will get me the IDs that I need in order to run function regionsla.

async function get_sla() {
  regionsids = [58, 59, 60, 61];
  americaids = [];
  europeids = [];
  asiaids = [];
  australiaids = [];
  for (const regionid of regionsids) {
    fetch('api.php', {
      // request body
    }).then(
      function(response) {
        response.json().then(
          function(data) {
            for (const label in data.result) {
              switch (regionid) {
                case 58:
                  americaids.push(data.result[label].serviceid);
                  break;
                case 59:
                  australiaids.push(data.result[label].serviceid);
                  break;
                case 60:
                  asiaids.push(data.result[label].serviceid);
                  break;
                case 61:
                  europeids.push(data.result[label].serviceid);
              }
            }
            switch (regionid) {
              case 58:
                regionsla(americaids, "America");
                averageAmerica = average;
                console.log(averageAmerica); //this returns                                                                          
                break; // average is not defined
              case 59:
                regionsla(australiaids, "Australia");
                break;
              case 60:
                regionsla(asiaids, "Asia");
                break;
              case 61:
                regionsla(europeids, "Europe");
            }
          })
      }
    );
  }
}
mplungjan
  • 169,008
  • 28
  • 173
  • 236
Bogdan993
  • 33
  • 4
  • Strange fetching. Here is the canonical fetch: `fetch('api.php') .then(response => response.json()) .then(data => console.log(data));` – mplungjan Nov 25 '21 at 09:12
  • THIS is a bad idea: `for (const regionid of regionsids) { fetch('api.php', {...).then(` Never loop ajax. Instead put the next call in the success or done of the fetch – mplungjan Nov 25 '21 at 09:13
  • Lastly a reduce with an average would be easier to read – mplungjan Nov 25 '21 at 09:14
  • But a fetch for one region id and then a switch sounds messy too. Why not `let americaids = []; fetch (api.php?region=58)`. But if it is your api, then ONE call for all of them should be enough – mplungjan Nov 25 '21 at 09:16

1 Answers1

0

The problem is with the scope of variables. Variables will be accessible only within the function they are declared. If you want to access the variable globally, declare it globally. May i know where is the Average variable declared?

As discussed in the comments following code will give you some ideas.

    function showName() {
  var result;`enter code here`
  result = addString('Hello', ' World');
  document.write (result );
}

// in below we will check how to return string from function
function addString(fName, lName) {
  var val;
  val = fName + lName;
  return val;  // returning string from function
}
  • it is assigned a value in the first function, inside the for loop: average = sum / i; The manual says: "If you assign a value to a variable that has not been declared, it will automatically become a GLOBAL variable" – Bogdan993 Nov 25 '21 at 10:18
  • Also, I tried declaring average=0; right in the beginning, outside of all functions, but then the value of average will always be 0. So the problem is not with the declaration, but with the fact that when jumping from function to function, its value is not retained. – Bogdan993 Nov 25 '21 at 10:20
  • I somewhat figured out what the issue is. – divakar raja Nov 25 '21 at 10:25
  • Try average1 = regionsla(americaids, "America"); in the function call. This will get the return statement in average1. Return the average value from the regionsla function. I have updated a sample code in my answer to give you some idea in how the function return works – divakar raja Nov 25 '21 at 10:27
  • 1
    The scope isn't the problem. Since the variable is never declared, it becomes a global variable or more accurately, a property on the `window` object (which is a very, very bad idea but that's not the issue here). The problem is that the function `regionsla` does an asynchronous call and since it's being called without waiting for the async process to finish, the next line (`averageAmerica = average`) runs before that global variable has been set. – Lennholm Nov 25 '21 at 10:40