• 0

[JavaScript] For Loop Cycling Through an Array


Question

I'm making a Minecraft server list for fun and for experience. When I try to run this code, it only displays that us.mineplex.com is up, and it is random. Sometimes it shows that 7 times, and sometimes 4.

 

JavaScript

        var servers = ["therealms.us", "craftboss.net", "us.mineplex.com"];
        for(var i=0;i<servers.length;i++){
            var ip = servers[i];
            var xhr = new XMLHttpRequest();
            xhr.open("GET", 'http://minecraft-api.com/v1/get/?server=' + ip, true);
            xhr.onreadystatechange = function() {
                    if (xhr.readyState === 4) {
                            data = JSON.parse(xhr.responseText);
                            if (data.status) {
                                    $("#server-status").append('<div class="alert alert-success">' + ip + ' is online!');
                            } else {
                                    $("#server-status").append('<div class="alert alert-danger">' + ip + ' is down!</div>');
                            }
                    }
            };
            xhr.send();
        }

HTML

      <div class="container">
          <div id="server-status"></div>
       </div>
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
    <script src="https://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>

Here is the documentation: http://minecraft-api.com/documentation#info

8 answers to this question

Recommended Posts

  • 0

Your problem probably stems from the fact that you're reusing your "xhr" object within the loop. In JavaScript, the only structure that creates scope is a function. If statements, loops, and other "block" structures do not create new scope. My guess would be that you're overwriting the "xhr" object each time your loop iterates, causing you to lose the callback for the previous GET request.

 

Since you're using jQuery already, I would suggest using its provided "$.Get" method. If you want to stick with custom "xhr" logic, you can extract that logic from the loop into it's own function. That should create the necessary scope that you're looking for.

        $(function() {
            var servers = ["therealms.us", "craftboss.net", "us.mineplex.com"];
            for (var i = 0; i < servers.length; i++) {
                var ip = servers[i];
                Get(ip);
            }

            function Get(ip) {
                var xhr = new XMLHttpRequest();
                xhr.open("GET", "/Home/Test?server=" + ip, true);
                xhr.onreadystatechange = function () {
                    if (xhr.readyState === 4) {
                        data = xhr.responseText;
                        if (data) {
                            $("#server-status").append("<div>" + data + "</div>");
                        }
                        else {
                            $("#server-status").append("<div>no data</div>");
                        }
                    }
                };
                xhr.send();
            }
        });

edit: also, if you haven't already; you should put your logic in jQuery's document ready function so that you make sure the DOM is loaded before you add to it. (I also fiddled with your logic a bit to fit my test, make sure you don't copy it exactly.)

  • Like 3
  • 0

Have you validated that the Minecraft API is returning the other servers being up as well?

 

 
  On 04/04/2014 at 17:15, 0sit0 said:

 

Does this work?

for(var i=0;i<servers.length-1;i++){

 

 

That would chop off the last element in the list.  You only need to subtract one if you're doing a "<=" comparison.

  • 0
  On 04/04/2014 at 17:17, spacer said:

Your problem probably stems from the fact that you're reusing your "xhr" object within the loop. In JavaScript, the only structure that creates scope is a function. If statements, loops, and other "block" structures do not create new scope. My guess would be that you're overwriting the "xhr" object each time your loop iterates, causing you to lose the callback for the previous GET request.

 

Since you're using jQuery already, I would suggest using its provided "$.Get" method. If you want to stick with custom "xhr" logic, you can extract that logic from the loop into it's own function. That should create the necessary scope that you're looking for.

        $(function() {
            var servers = ["therealms.us", "craftboss.net", "us.mineplex.com"];
            for (var i = 0; i < servers.length; i++) {
                var ip = servers[i];
                Get(ip);
            }

            function Get(ip) {
                var xhr = new XMLHttpRequest();
                xhr.open("GET", "/Home/Test?server=" + ip, true);
                xhr.onreadystatechange = function () {
                    if (xhr.readyState === 4) {
                        data = xhr.responseText;
                        if (data) {
                            $("#server-status").append("<div>" + data + "</div>");
                        }
                        else {
                            $("#server-status").append("<div>no data</div>");
                        }
                    }
                };
                xhr.send();
            }
        });

edit: also, if you haven't already; you should put your logic in jQuery's document ready function so that you make sure the DOM is loaded before you add to it. (I also fiddled with your logic a bit to fit my test, make sure you don't copy it exactly.)

Yeah, I was thinking that it was something like that. I'll recode it to be somewhat like your logic, and I'll see if it works.

  • 0
  On 04/04/2014 at 17:17, spacer said:

Your problem probably stems from the fact that you're reusing your "xhr" object within the loop. In JavaScript, the only structure that creates scope is a function. If statements, loops, and other "block" structures do not create new scope. My guess would be that you're overwriting the "xhr" object each time your loop iterates, causing you to lose the callback for the previous GET request.

 

Really!?  That's rather counter-intuitive.  Suddenly I feel less bad that the Mozilla CEO, creator of JS, quit if he designed it to work like that. :P

  • 0
  On 04/04/2014 at 17:44, Audien said:

Really!?  That's rather counter-intuitive.  Suddenly I feel less bad that the Mozilla CEO, creator of JS, quit if he designed it to work like that. :p

Yeah, it's definitely odd coming from a more structured language like C++ or C#. But it's also a reason why functional languages are great. They are incredibly flexible and expressive once you understand the quirks.  :)

 

  On 04/04/2014 at 17:45, mastercoms said:

It works. :)

Glad to hear it.

  • 0
  On 04/04/2014 at 17:59, spacer said:

Yeah, it's definitely odd coming from a more structured language like C++ or C#. But it's also a reason why functional languages are great. They are incredibly flexible and expressive once you understand the quirks.  :)

I'd say it's more a failure of JavaScript's crappy variable scoping rules than anything. Functional languages are great, but JavaScripts variable scope rules are most certainly not.

  • Like 1
This topic is now closed to further replies.
  • Posts

    • "This is despite the company inching closer to a $4 trillion market cap with each passing day." Sigh, you realise Microsoft doesn't own that $4T, right? That money is owned by investors. In fact, Microsoft is expected to hand out dividends which does come out of operating revenue, so that much market capitalisation can actually be a drain on a company, not a benefit. Microsoft's actual revenue in 2024 was around $375B with reported earnings of $155B which means that 59% of its earnings were eaten by expenses. You could legitimately argue that $155B is still a lot of money, so why lay off those workers? If we assume an average salary of $90K per worker, 9,000 workers mean $810M just in wages, which seems like small beans compared to $155B. But seriously, people have to get over market cap as a metric of anything other than investor confidence. It is NOT the measure of the actual worth of a company.
    • Looking forward to this.
    • You know - if you abbreviate 2038 as 2K38, it's exactly the same number of characters and so isn't actually an abbreviation - and worse, just makes it confusing for people who weren't aware of the original Y2K problem which happened 25 years ago.
    • This only works for sites that care about the law. Anyone who can't or doesn't want to meet the requirements will either use a VPN or go to a (piracy) alternative that doesn't care about the law. It'll be even worse than the people having visited the law abiding sites without the verification. So way to go on that one.
  • Recent Achievements

    • Dedicated
      EYEREX earned a badge
      Dedicated
    • First Post
      Electronic Person earned a badge
      First Post
    • Week One Done
      CyberCeps666 earned a badge
      Week One Done
    • Very Popular
      d4l3d earned a badge
      Very Popular
    • Dedicated
      Stephen Leibowitz earned a badge
      Dedicated
  • Popular Contributors

    1. 1
      +primortal
      606
    2. 2
      ATLien_0
      235
    3. 3
      Xenon
      159
    4. 4
      neufuse
      131
    5. 5
      +FloatingFatMan
      124
  • Tell a friend

    Love Neowin? Tell a friend!