0

function par(idF, idM) {
  this.IDOvna = idM;
  this.IDOvce = idF;

}



function breeding() {
  let idOvce = [];
  let brOvce = [];
  let mesecOvce = [];
  let godinaOvce = [];
  let istorija1 = [];
  let istorija2 = [];

  let idOvna = [];
  let brOvna = [];
  let mesecOvna = [];
  let godinaOvna = [];

  let y = 0;
  let o = 0;
  let parovi = [];
  let c = 0;
  fetch("http://localhost/ovce/ovce.json")
    .then(function(resp) {
      return resp.json();
    })
    .then(function(data) {
      console.log(data);
      for (let i = 0; i < data.ovce.length; i++) {
        idOvce[i] = data.ovce[i].id;
        brOvce[i] = data.ovce[i].broj;
        mesecOvce[i] = data.ovce[i].mesec;
        godinaOvce[i] = data.ovce[i].godina;
        istorija1[i] = data.ovce[i].istorija1;
        istorija2[i] = data.ovce[i].istorija2;
      }
    });
  fetch("http://localhost/ovce/ovnovi.json")
    .then(function(resp1) {
      return resp1.json();
    })
    .then(function(data1) {
      console.log(data1);
      for (let g = 0; g < data1.ovnovi.length; g++) {
        idOvna[g] = data1.ovnovi[g].id;
        brOvna[g] = data1.ovnovi[g].broj;
        mesecOvna[g] = data1.ovnovi[g].mesec;
        godinaOvna[g] = data1.ovnovi[g].godina;
      }
    });

  while (o < idOvna.length) {
    y = 0;
    while (y < idOvce.length) {
      if (istorija1[y] != 0) {
        if ((istorija2[y] != idOvna[o]) && (istorija2[istorija1[y]] != idOvna[o])) {
          parovi[c] = new par(idOvce[y], idOvna[o]);
          c++;
        }
      } else {
        parovi[c] = new par(idOvce[y], idOvna[o]);
        c++;
      }
      y++;
    }
    o++;
  }
  console.log(parovi);
  return parovi;
}
<html>

<head>
  <title>Sheepify</title>
  <script src="main.js"></script>
</head>

<body>
  <button onclick="breeding()"> Breeding </button>
</body>

</html>

In javascript, i have a loop running and afterwards the pairs array which should be populated is empty.

function pair(idF, idM) {
  this.IDOvna = idM;
  this.IDOvce = idF;
}

function problem() {
  let y = 0;
  let o = 0;
  let pairs = [];
  let c = 0;

  //id, id1, history1, history2 are arrays which are populated from the json files using fetch.

  while (o < id.length) {
    y = 0;
    while (y < id1.length) {
      if (history1[y] != 0) {
        if ((history2[y] != id[o]) && (history2[history1[y]] != id[o])) {
          pairs[c] = new pair(id1[y], id[o]);
          c++;
        }
      } else {
        pairs[c] = new pair(id1[y], id[o]);
        c++;
      }
      y++;
    }
    o++;
  }
  console.log(pairs);
  console.log(pairs.length);
}

When i run a debugger the array is populated and everything is fine, but when i execute the function on button click or through a console, it just returns an empty array. What could be causing this problem? EDIT: I accidentally pasted the pair function inside the problem function, which isn't the case. I have moved it out now. And changed leght to length as suggested. EDIT2: Here is the full code, sorry about the variable names, they are in Serbian.

MilanJ
  • 5
  • 4
  • 2
    It would help if you included the values of all the arrays you're accessing. Also, the code would be easier to read if you used `for` loops instead of `while`, and `pairs.push()`. – Barmar Aug 28 '20 at 14:09
  • Are you sure the arrays contain values that fit the criteria used to add pairs to the array? – Barmar Aug 28 '20 at 14:10
  • The `pairs` variable is local to the function. How do you use it in the button click? – Barmar Aug 28 '20 at 14:11
  • Please post a [mcve]. You can use a [Stack Snippet](https://meta.stackoverflow.com/questions/358992/ive-been-told-to-create-a-runnable-example-with-stack-snippets-how-do-i-do) to make it executable. – Barmar Aug 28 '20 at 14:11
  • `fetch()` is asynchronous. Are you sure the fetch has completed before you run this function? – Barmar Aug 28 '20 at 14:12
  • 1
    You need to run this in the `.then()` callback of `fetch()`. Otherwise the arrays won't be populated. – Barmar Aug 28 '20 at 14:13
  • See https://stackoverflow.com/questions/23667086/why-is-my-variable-undefined-after-i-modify-it-inside-of-a-function-asynchron – Barmar Aug 28 '20 at 14:14
  • I don't think fetch is the problem here since all the variables populated using fetch are fine, pairs array doesn't have anything to do with fetch. – MilanJ Aug 28 '20 at 14:18
  • Put `console.log(JSON.stringify(id), JSON.stringify(id1), JSON.stringify(history1), JSON.stringify(history2))` before the `while` loop. Make sure you use `JSON.stringify` so you see the arrays at that time; if you just log the arrays, the console updates when the arrays are filled in. – Barmar Aug 28 '20 at 14:21
  • 1
    You say that the variables are all populated, but you could be wrong. Post the actual code. – Barmar Aug 28 '20 at 14:21
  • Thank you for the feedback i will try adding the console.log statement you suggested. Also, i have posted the actual code in the snippet, but the variable names are in Serbian, so I hope it helps. – MilanJ Aug 28 '20 at 14:25
  • It's exactly what we said. The loop is not in the `.then()` functions, so the arrays have not been populated. – Barmar Aug 28 '20 at 14:30
  • So what you are saying is that all the variables populated in the promise or `.then()` of the fetch lose their value outside the `.then()` section? – MilanJ Aug 28 '20 at 14:33
  • They don't lose their values, the values haven't been set yet. Do you understand how asynchronous functions work? – Barmar Aug 28 '20 at 14:34
  • `fetch()` returns *before* the callbacks have been executed. – Barmar Aug 28 '20 at 14:34
  • Did you read the question I linked to above? – Barmar Aug 28 '20 at 14:35
  • Oooh, okay now i get it. Thank you very much :D – MilanJ Aug 28 '20 at 14:39

2 Answers2

2

The loop that processes the arrays is outside the fetch callback functions, so it doesn't wait for the arrays to be populated. See Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference.

You can make your function async and use await to wait for them.

Note also that the code that calls this will need to use await or .then() to get the returned parovi array. See How do I return the response from an asynchronous call?

async function breeding() {
  let idOvce = [];
  let brOvce = [];
  let mesecOvce = [];
  let godinaOvce = [];
  let istorija1 = [];
  let istorija2 = [];

  let idOvna = [];
  let brOvna = [];
  let mesecOvna = [];
  let godinaOvna = [];

  let y = 0;
  let o = 0;
  let parovi = [];
  let c = 0;
  await fetch("http://localhost/ovce/ovce.json")
    .then(function(resp) {
      return resp.json();
    })
    .then(function(data) {
      console.log(data);
      for (let i = 0; i < data.ovce.length; i++) {
        idOvce[i] = data.ovce[i].id;
        brOvce[i] = data.ovce[i].broj;
        mesecOvce[i] = data.ovce[i].mesec;
        godinaOvce[i] = data.ovce[i].godina;
        istorija1[i] = data.ovce[i].istorija1;
        istorija2[i] = data.ovce[i].istorija2;
      }
    });
  await fetch("http://localhost/ovce/ovnovi.json")
    .then(function(resp1) {
      return resp1.json();
    })
    .then(function(data1) {
      console.log(data1);
      for (let g = 0; g < data1.ovnovi.length; g++) {
        idOvna[g] = data1.ovnovi[g].id;
        brOvna[g] = data1.ovnovi[g].broj;
        mesecOvna[g] = data1.ovnovi[g].mesec;
        godinaOvna[g] = data1.ovnovi[g].godina;
      }
    });

  while (o < idOvna.length) {
    y = 0;
    while (y < idOvce.length) {
      if (istorija1[y] != 0) {
        if ((istorija2[y] != idOvna[o]) && (istorija2[istorija1[y]] != idOvna[o])) {
          parovi[c] = new par(idOvce[y], idOvna[o]);
          c++;
        }
      } else {
        parovi[c] = new par(idOvce[y], idOvna[o]);
        c++;
      }
      y++;
    }
    o++;
  }
  console.log(parovi);
  return parovi;
}

function par(idF, idM) {
  this.IDOvna = idM;
  this.IDOvce = idF;
}
<html>

<head>
  <title>Sheepify</title>
  <script src="main.js"></script>
</head>

<body>
  <button onclick="breeding()"> Breeding </button>
</body>

</html>
Barmar
  • 741,623
  • 53
  • 500
  • 612
-1

how are you using this problem function within the fetch?

If you are using int outside the fetch its totaly normal, your arrays will be empty.

Edit:

As you have post the fetch method, you need to put all your while loop un the last then, when you are populating the data, because fetch is async =/ Since you have two fetch, and both are populating the array's you need to do the second in the last then of the first fetch. And finaly you can do your while loop in last then of your second fetch. It may be more clearner using async await method.

function par(idF, idM) {
    this.IDOvna = idM;
    this.IDOvce = idF;
}
  
  
  
function breeding() {
    let idOvce = [];
    let brOvce = [];
    let mesecOvce = [];
    let godinaOvce = [];
    let istorija1 = [];
    let istorija2 = [];

    let idOvna = [];
    let brOvna = [];
    let mesecOvna = [];
    let godinaOvna = [];

    let y = 0;
    let o = 0;
    let parovi = [];
    let c = 0;
    fetch("http://localhost/ovce/ovce.json")
    .then(function(resp) {
    return resp.json();
    })
    .then(function(data) {
    console.log(data);
    for (let i = 0; i < data.ovce.length; i++) {
        idOvce[i] = data.ovce[i].id;
        brOvce[i] = data.ovce[i].broj;
        mesecOvce[i] = data.ovce[i].mesec;
        godinaOvce[i] = data.ovce[i].godina;
        istorija1[i] = data.ovce[i].istorija1;
        istorija2[i] = data.ovce[i].istorija2;
    }

    fetch("http://localhost/ovce/ovnovi.json")
    .then(function(resp1) {
    return resp1.json();
    })
    .then(function(data1) {
        console.log(data1);
        for (let g = 0; g < data1.ovnovi.length; g++) {
            idOvna[g] = data1.ovnovi[g].id;
            brOvna[g] = data1.ovnovi[g].broj;
            mesecOvna[g] = data1.ovnovi[g].mesec;
            godinaOvna[g] = data1.ovnovi[g].godina;

            while (o < idOvna.length) {
            y = 0;
            while (y < idOvce.length) {
                if (istorija1[y] != 0) {
                if ((istorija2[y] != idOvna[o]) && (istorija2[istorija1[y]] != idOvna[o])) {
                    parovi[c] = new par(idOvce[y], idOvna[o]);
                    c++;
                }
                } else {
                parovi[c] = new par(idOvce[y], idOvna[o]);
                c++;
                }
                y++;
            }
            o++;
            }
            console.log(parovi);
            return parovi;
        }
        });
    });
    

}
eltha
  • 53
  • 1
  • 6
  • In his code he right that the arrays are populated using a fetch on a json file – eltha Aug 28 '20 at 14:12
  • Everything is inside the `problem` function, I just didn't think it was necessary to include the fetch part because it wasn't relevant to the issue, since the data assignment is working fine. – MilanJ Aug 28 '20 at 14:13
  • 1
    Welcome to Stack Overflow! This is really a comment, not an answer. With a bit more rep, [you will be able to post comments](//stackoverflow.com/privileges/comment). I've posted a similar comment for you. – Barmar Aug 28 '20 at 14:13
  • I think the fetch is the key of your problem, – eltha Aug 28 '20 at 14:14
  • Thank's @Barmar , it's hard when we start, plenty of question and i can't ask them, so ... yes i'm using the Answer area =/ sorry – eltha Aug 28 '20 at 14:17
  • @Barmar if he think's this fetch is working great, can he populate by hand the arrays and share for us to check ? (please comment this haha ) – eltha Aug 28 '20 at 14:24
  • I have, I have shared the full code. – MilanJ Aug 28 '20 at 14:30
  • I edit my edit if you want to read, @Barmar response is better unsing async await method, but if you want to keep with the then method is like that – eltha Aug 28 '20 at 14:41