0

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?

2
  • 1
    I would certainly not advise to pass false as value for the async argument. Embrace the power of promises and asynchronous programming instead. Commented Jul 5, 2020 at 16:19
  • I would suggest attempting to use the result of the requests in a way that does not rely on order. Is that a possibility? Commented Jul 5, 2020 at 16:36

2 Answers 2

3

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

Sign up to request clarification or add additional context in comments.

7 Comments

I think this is too advanced for OP however since, you're down that road, may I suggest to chunk the outrageous 50 async requests to maybe 5 at a time? :)
The OP already did those simultaneous requests at the same time and apparently without a problem.
@MuhammadTalhaAkbar fetch is the standard therefor I can't consider this is advanced. Actually it's much easier than XMLHttpRequest.
Well, it makes more sense. Even though, I think that XMLHttpRequest is more complicated and really shouldn't be in use in 2020. IMHO of course :)
And once you say fetch, you say promises.
|
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.