node ninja
node ninja

Reputation: 32986

How does the XMLHttpRequest() object do this?

I've been studying JavaScript for a while and when I started to learn AJAX I saw something I have never seen before that is curious.

Take this sample code for example.

var receiveReq = XMLHttpRequest();      
//Initiate the asyncronous request.
function sayHello() {
    //If our XMLHttpRequest object is not in the middle of a request, start the new asyncronous call.
    if (receiveReq.readyState == 4 || receiveReq.readyState == 0) {
        //Setup the connection as a GET call to SayHello.html.
        //True explicity sets the request to asyncronous (default).
        receiveReq.open("GET", 'SayHello.html', true);
        //Set the function that will be called when the XMLHttpRequest objects state changes.
        receiveReq.onreadystatechange = handleSayHello; 
        //Make the actual request.
        receiveReq.send(null);
    }           
}

function handleSayHello() {
    //Check to see if the XmlHttpRequests state is finished.
    if (receiveReq.readyState == 4) {
        //Set the contents of our span element to the result of the asyncronous call.
        document.getElementById('span_result').innerHTML = receiveReq.responseText;
    }           
}

Once this function is called, it's like the browser continues to call handleSayHello() multiple times. What causes the browser do this? I have never seen that in JavaScript before, or any language really, and it doesn't make sense to me. How does that work? Are there other things in JavaScript that are like this?

Also, what would happen if receiveReq.readyState was not 0 or 4 when the if statement in sayHello() ran?

Edit:

I made a small change to the function sayHello() and it looks like this now.

function sayHello() {
    //If our XmlHttpRequest object is not in the middle of a request, start the new asyncronous call.
    if (receiveReq.readyState == 4) {
        //Setup the connection as a GET call to SayHello.html.
        //True explicity sets the request to asyncronous (default).
        receiveReq.open("GET", 'SayHello.html', true);
        //Set the function that will be called when the XmlHttpRequest objects state changes.
        receiveReq.onreadystatechange = handleSayHello; 
        //Make the actual request.
        receiveReq.send(null);
    }     
    else
        alert("readyState = " + receiveReq.readyState);      
}

The code still works! What I found is that this if statement gets executed once. The first time is when readyState = 0 and the second time is when readyState = 4. How did that happen?

Here's the complete source code.

<html>
    <head>
        <title>The Hello World of AJAX</title>
        <script language="JavaScript" type="text/javascript">
            //Gets the browser specific XMLHttpRequest Object
            function getXmlHttpRequestObject() {
                if (window.XMLHttpRequest) {
                    return new XMLHttpRequest(); //Not IE
                } else if(window.ActiveXObject) {
                    return new ActiveXObject("Microsoft.XMLHTTP"); //IE
                } else {
                    //Display your error message here. 
                    //and inform the user they might want to upgrade
                    //their browser.
                    alert("Your browser doesn't support the XmlHttpRequest object.  Better upgrade to Firefox.");
                }
            }           
            //Get our browser specific XMLHttpRequest object.
            var receiveReq = getXmlHttpRequestObject();     
            //Initiate the asyncronous request.
            function sayHello() {
                //If our XMLHttpRequest object is not in the middle of a request, start the new asyncronous call.
                if (receiveReq.readyState == 4 || receiveReq.readyState == 0) {
                    //Setup the connection as a GET call to SayHello.html.
                    //True explicity sets the request to asyncronous (default).
                    receiveReq.open("GET", 'SayHello.html', true);
                    //Set the function that will be called when the XMLHttpRequest objects state changes.
                    receiveReq.onreadystatechange = handleSayHello; 
                    //Make the actual request.
                    receiveReq.send(null);
                }           
            }
            //Called every time our XMLHttpRequest objects state changes.
            function handleSayHello() {
                //Check to see if the XMLHttpRequest's state is finished.
                if (receiveReq.readyState == 4) {
                    //Set the contents of our span element to the result of the asyncronous call.
                    document.getElementById('span_result').innerHTML = receiveReq.responseText;
                }
            }
            </script>
    </head>
    <body>
        <!-- Clicking this link initiates the asyncronous request -->
        <a href="javascript:sayHello();">Say Hello</a><br />
        <!-- used to display the results of the asynchronous request -->
        <span id="span_result"></span>
    </body>
</html>

The content of SayHello.html is just

hello, world

Upvotes: 2

Views: 692

Answers (2)

Torrent Lee
Torrent Lee

Reputation: 845

every time you what a request ,you need a new XHR instance
when xhr's readyState changed, onreadystatechange event listener will be call
so

function sayHello() {
    var receiveReq = new XMLHttpRequest();      
    receiveReq.open("GET", 'SayHello.html', true);
    receiveReq.onreadystatechange = function  (  ) {
        if (receiveReq.readyState == 4 ) {
        //do sth.
            handleSayHello ()
        }
    }; 
    receiveReq.send(null);
}
function handleSayHello (  ) {

}

Upvotes: 0

rwilliams
rwilliams

Reputation: 21487

The following line of code is hooking the onreadystatechange event to your handleSayHello function. onreadystatechange is fired a number of times during the life cycle of an XMLHttpRequestrequest hence the handle function is running more than once.

receiveReq.onreadystatechange = handleSayHello; 

This article is pretty informative with regards to readystate values and changes.

Upvotes: 3

Related Questions