Reputation: 32986
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
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
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