Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XMLHttpRequest in for loop

I am trying to make several server requests inside a for loop. I found this question and implemented the suggested solution. However it doesn't seem to work.

    for (var i = 1; i <= 10; i++)
    {
    (function(i) {
    if(<some conditions>)
    {
    if (window.XMLHttpRequest) {
        // code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp[i]=new XMLHttpRequest();
      } else { // code for IE6, IE5
        xmlhttp[i]=new ActiveXObject("Microsoft.XMLHTTP");
      }
      xmlhttp[i].onreadystatechange=function() {
        if (xmlhttp[i].readyState==4 && xmlhttp[i].status==200) {
          document.getElementById("preselection").innerHTML=xmlhttp[i].responseText;
        }
      }
      xmlhttp[i].open("GET","getBuoys.php?q="+i,true);
      xmlhttp[i].send();
    }
})(i);
}

If I remove the for loop and change all xmlhttp[i] to xmlhttp, everything works just fine for one element, but I can't make several requests. Thanks in advance for any suggestions.

like image 858
Axel Avatar asked Aug 09 '14 16:08

Axel


People also ask

Is XMLHttpRequest deprecated?

Synchronous request. Warning: Synchronous XHR requests often cause hangs on the web, especially with poor network conditions or when the remote server is slow to respond. Synchronous XHR is now deprecated and should be avoided in favor of asynchronous requests.

What does XMLHttpRequest do in JavaScript?

XMLHttpRequest (XHR) objects are used to interact with servers. You can retrieve data from a URL without having to do a full page refresh. This enables a Web page to update just part of a page without disrupting what the user is doing. XMLHttpRequest is used heavily in AJAX programming.

What is meant by XMLHttpRequest?

XMLHttpRequest (XHR) is a JavaScript API to create AJAX requests. Its methods provide the ability to send network requests between the browser and a server.


2 Answers

Try the snippet below

// JavaScript
window.onload = function(){

    var f = (function(){
        var xhr = [], i;
        for(i = 0; i < 3; i++){ //for loop
            (function(i){
                xhr[i] = new XMLHttpRequest();
                url = "closure.php?data=" + i;
                xhr[i].open("GET", url, true);
                xhr[i].onreadystatechange = function(){
                    if (xhr[i].readyState === 4 && xhr[i].status === 200){
                        console.log('Response from request ' + i + ' [ ' + xhr[i].responseText + ']'); 
                    }
                };
                xhr[i].send();
            })(i);
        }
    })();

};

// PHP [closure.php]
echo "Hello Kitty -> " . $_GET["data"];

Response

Response from request 0 [ Hello Kitty -> 0]
Response from request 1 [ Hello Kitty -> 1]
Response from request 2 [ Hello Kitty -> 2] 
like image 67
hex494D49 Avatar answered Sep 29 '22 01:09

hex494D49


First thing first, that's awful formatting. A small request to keep it a bit more parseable in future please.

We can clean this up though.

var XMLHttpRequest
  = XMLHttpRequest || require('xmlhttprequest').XMLHttpRequest;

// Makes a request for 4 buoy page responses.
requestAllBuoys(4, function(requests) {

  console.log('Got results!');

  // Take out the responses, they are collected in the order they were
  // requested.
  responses = requests.map(function(request) {
    return request.responseText;
  });

  // Left to you to implement- I don't know what you're going to do with
  // your page!
  updateDom(responses);

});

// Makes request to all buoy url's, calling the given callback once
// all have completed with an array of xmlRequests.
function requestAllBuoys (n, cb) {

  var latch = makeLatch(n, cb);

  makeBuoyURLTo(n).map(function (url, i) {
    startXMLRequest('GET', url, latch.bind(undefined, i));
  });

}

// Generates a latch function, that will execute the given callback
// only once the function it returns has been called n times.
function makeLatch (n, cb) {

  var remaining = n,
      results = [],
      countDown;

  countDown = function (i, result) {
    results[i] = result;
    if (--remaining == 0 && typeof cb == 'function') {
      cb(results);
    }
  }

  return countDown;

}

// Generates an array of buoy URL's from 1 to n.
function makeBuoyURLTo (n) {

  var i, buoyUrls = [];

  for (i = 1; i <= n; i++) {
    buoyUrls.push('getBuoys.php?q=' + i);
  }

  return buoyUrls;

}

// Create and initiate an XMLRequest, with the given method to the given url.
// The optional callback will be called on successful completion.
function startXMLRequest (method, url, cb) {

  var xmlRequest = createXMLRequest();

  xmlRequest.onreadystatechange = function () {
    if (isXMLFinished(xmlRequest)) {
      if (cb && typeof cb == 'function') {
        cb(xmlRequest, method, url);
      }
    }
  }

  xmlRequest.open(method, url, true);
  xmlRequest.send();

  return xmlRequest;

}

// Initiates an XMLRequest from either HTML5 native, or MS ActiveX depending
// on what is available.
function createXMLRequest () {

  var xmlRequest;

  if (XMLHttpRequest) {
    xmlRequest = new XMLHttpRequest();
  } else {
    xmlRequest = new ActiveXObject('Microsoft.XMLHTTP');
  }

  return xmlRequest;

}

// Verifies that XMLRequest has finished, with a status 200 (OK).
function isXMLFinished (xmlRequest) {
  return (xmlRequest.readyState == 4) && (xmlRequest.status == 200);
}

This may seem longer, but it makes things infinitely clearer, and the time you spent making it so is time you don't spend debugging.

It also allows you to access the final result together, in the order that they came as a standard array. This is the main added bulk.

I would say you have a good idea of what you're actually doing here, as to me the only thing about your code that wouldn't work is the updating of the dom (surely you'll just be assigning them rapidly all into the same element? replacing each other each time...).

Have a look at this answer about handling async callbacks if you're still struggling. But please, for your own sake, keep your code cleaner.

like image 38
Lawrence Jones Avatar answered Sep 28 '22 23:09

Lawrence Jones