Reputation: 343
I got 50 JSON files. (1.json, 2.json ... 50.json). The structure for each one is:
{
"book": "Księga Wyjścia",
"chapter": 1,
"type": "verses",
"verses": [
{
"text": "Oto imiona synów Izraela, którzy razem z Jakubem przybyli do Egiptu. Każdy zaś przyszedł ze swoją rodziną:",
"verse": "1"
},
{
"text": "Ruben, Symeon, Lewi, Juda;",
"verse": "2"
},
{
"text": "Issachar, Zabulon i Beniamin;",
"verse": "3"
},
{
"text": "Dan, Neftali, Gad i Aser.",
"verse": "4"
},
{
"text": "Było zaś wszystkich potomków Jakuba siedemdziesiąt osób, Józef zaś już był w Egipcie.",
"verse": "5"
}
]
}
There are more verses in every file and the size of each one can be completely different (so they don't load immediately). I load "chapter" node. Each time I refresh the file, I got different order, ie. (just last few numbers from last reshresh): 28,35,32,36,37,29,30,31,38,33,49,50,39,40,41,42,43,44,45,46,47,48
<script>
for (i = 1; i <= 50; i++) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var input = JSON.parse(this.responseText);
console.log(input.chapter);
}
};
xmlhttp.open("GET", (i + ".json"), true);
xmlhttp.send();
}
</script>
I assume it's because it loads asynchronous. Can I force my script to load synchronous?
Upvotes: 0
Views: 50
Reputation: 10030
You should keep the requests asynchronous because not only it would save the loading time but, if any of the requests take too long to respond, no other chapter will be loaded until that request resolves.
As a start, I would suggest you create a responses
array and in the callback, push the JSON response to that array and check for the number of responses
received so far, when the number responses are 50, it means all of the chapters are loaded. At that point, sort()
the responses
based on chapter
. Once done, you will then be able to go ahead and doSomething()
.
Note: You need to define doSomething()
function that takes all of the chapters in order as an input and does something with them.
<script>
var responses = [];
for (i = 1; i <= 50; i++) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var input = JSON.parse(this.responseText);
responses.push(input);
if (responses.length === 50) {
responses = responses.sort(function(a, b) {
return a.chapter < b.chapter;
});
doSomething(responses);
}
}
};
xmlhttp.open("GET", (i + ".json"), true);
xmlhttp.send();
}
</script>
Like @MoshFeu and @trincot suggested, it is way easier to use fetch
and if you get your head around Promise
, you will be far better off with Promise
and async/await
syntax for all the asynchronous work.
Upvotes: 0
Reputation: 350137
Use the fetch
API and the power of promises:
let promises = [];
for (let i = 1; i <= 50; i++) {
promises.push(fetch(i + ".json").then(resp => resp.json());
}
Promise.all(promises).then(function(inputs) {
inputs.forEach(input => console.log(input.chapter));
});
Even though the promises may resolve in a different order, Promise.all
will resolve to an array of responses that maintains the original order of the promises it got.
NB: make sure you define your variables (like i
) with var
, let
or const
Upvotes: 3