To those of you who are used to my typical crazy picture/funny
video/interesting stuff post, you will have to excuse me a few posts to
talk about nerdy things. This being one of those posts. Unless you care
about programming, stop reading now.
How ajax works
Building the new style web 2.0 sites that contain Ajax functionality
is actually quite simple, especially now with the multitude of
frameworks being released to simplify this (Atlas, jQuery, etc). But I
am a bit old school and like to know exactly what is happening when my
code executes as opposed to using pre-built functions and assuming they
will work for every scenario I must handle. Sure, these frameworks are
great for RAD and applications that are only used in-house (because you
can hack the backend to pieces without worries for security really,
unless you must provide role based access in the application). We will
be dealing with a simple page containing raw javascript and php.
There are at least two files required for a simple ajax example. One
is an HTML file containing the javascript to make the request from the
client to the web server. The other is a script to receive the request,
process it, and return the information to the client javascript.
If you do not understand how a basic ajax request works, consider it
nothing more than a client/server connection. The client is your
visitor, and the server is of course your server. When you attach
javascript to an HTML file, that javascript code is executed on the
visitors machine and can save your server some memory as well as cpu
cycles. The browser sees this javascript code and interprets it and
then executes it. An ajax request is nothing more than using javascript
to create a socket, send a request to your server, and process the
returned data with javascript. A query would go as follows:
Clients requests www.mysite.com/index.html -> javascript
code on index.html creates a socket on visitors computer -> socket
sends request to www.mysite.com/ajax.php -> ajax.php processes the
request and sends back information (aka "hello world") -> visitors
computer gets the data ("hello world") and decides what to do with it
on the page (show it as an alert, show it in a text box, show it as an
error).
This allows an entire website to be built in such a way that the
visitor actually never has to load another page. The entire website
could simply be sent back and forth using ajax and show the returned
data on the page as it gets it. Want an example of how this can be used
in a very efficient manner? Take a glance at Bing Image Search.
Do a search for anything and scroll down. Notice how you never have to
click a "Next Page" to get more results, it simply continues to load
new images as you scroll down, always staying one step ahead. Well, in
this case it is nothing more than ajax being used and the request sent
being "gather more images", and so bing.com passes back more images,
and your web browser says, "add new images to image listing". Another
example of this that most people don't notice is the search suggestion
feature at Google. Notice if you type in a few words you will get
suggestions of what to search for by Google. It simply passes what you
type to google as you type it, and returns back searches related to
what you have typed so far, your browser is told via javascript to
"list them here". Pretty neat eh?
A simple ajax request (example code)
Let's dive into some code here and get our hands dirty. A quick
"Hello World" example using ajax and php requires two files: ajax.php
and ajax.html. The source code for these files is below. I would
suggest you manually type them instead of simply copy and paste if you
feel weak about understanding all of this. If you feel you have a good
idea about what's going on go ahead and copy and paste. I only suggest
manually typing it for newbies because it forces you to look at the
code line by line and understanding it.
ajax.html
<html>
<head><title>Ajax Hello World Example (www.amusingmarlow.com)</title></head>
<script language="javascript">
function socketsetup() {
if (window.XMLHttpRequest)
httpsocket = new XMLHttpRequest();
else if (window.ActiveXObject)
httpsocket = new ActiveXObject("Microsoft.XMLHTTP");
httpsocket.open("GET","ajax.php",true);
httpsocket.onreadystatechange=socketreceive;
if(window.XMLHttpRequest)
httpsocket.send(null);
else if(window.ActiveXObject)
httpsocket.send();
}
function socketreceive() {
if(httpsocket.readyState==4) {
if(httpsocket.status==200 || httpsocket.status==304) {
document.getElementById('received').innerHTML=httpsocket.responseText;
}
}
}
</script>
</head>
<body>
<div id="received"></div><br />
<input onclick="socketsetup();" type="button" value="Grab Data" />
</body>
</html>
ajax.php
<?php
echo 'Hello World. This is an ajax test.';
?>
Save the two files above, upload them, and visit
http://www.yoursite.com/ajax.html. You should see a blank page titled
"Ajax Hello World Example" with a button saying "Grab Data". Click this
button and you will instantly see the message from ajax.php (well,
depending on how fast your server and computer are). Congratulations!
You just ran your first ajax script.
The real question is, do you understand the code? No? Well that is
fine, I will explain line by line exactly what is going on here.
Simple Ajax Request Code Explanation
The first thing you must understand is where the call to the ajax
javascript happens. In our example script above look at the html line:
<input onclick="socketsetup();" type="button" value="Grab Data" />
Nothing but simple html here, which you should be very familiar
with, and a call to the function "socketsetup" when the onclick action
occurs. When someone clicks the button, it calls "socketsetup", easy
enough.
Our first dive into the actual javascript will be with the function
"socketsetup". Looking at the first few lines of the function you see:
if (window.XMLHttpRequest)
httpsocket = new XMLHttpRequest();
else if (window.ActiveXObject)
httpsocket = new ActiveXObject("Microsoft.XMLHTTP");
The code here does nothing more than setup a "socket" using
javascript, which we can later use to send/receive data from the
browser to our server. In our case the socket name is "httpsocket". You
may be asking, "Why is there an if/then statement required for this?".
Well, the browser wars is your answer. See, in Firefox and most other
browsers you can simply call:
httpsocket=new XMLHttpRequest();
But the problem occurs with our dear old friend Internet Explorer.
In internet explorer microsoft has a different way to declare this new
socket object, using ActiveX. The way we do this is:
httpsocket = new ActiveXObject("Microsoft.XMLHTTP");
The next couple of lines in this function are responsible for
opening our connection and setting a receive function. To open the
connection we call:
httpsocket.open("GET","ajax.php",true);
There are three parameters passed to the open() function, actually
more exist but they are optional parameters. Actually only the first
two parameters here are necessary for the code to work, but we pass a
third to improve the quality of the script significantly.
Our first parameter, "GET", tells the socket that this will be a GET request, as opposed to a POST.
Side Note:If you are not sure what the
difference between a GET and a POST request is, you may want to turn
back now and look into some simpler tutorials of a basic php form. Ajax
at the moment is a hot trend on the web and you may be anxious to use
it, but you must crawl before you walk. Plenty of fantastic websites
still use nothing more than basic forms and without detailed knowledge
of basic forms, using ajax can not only impede development but lead to
severe security related problems.
Our second parameter in this line of code tells the object which
page to fetch. In our case this is ajax.php, which will then return our
data to the object, which is then passed to the "onreadystatechange"
function (you will see this line of code in a second).
The third parameter is a tricky one to explain unless you have a
basic understanding of how sockets work. Chances are if you understand
this you already know what ajax is and already know how to use it,
making this a moot point for you. Nevertheless, I will tell you that
the third parameter has to deal with asynchronism. This can be a
difficult thing for beginners to understand so listen up close: When
you make a connection with a normal socket, you open the connection,
send the data, get data back, and then do whatever you wish. It is done
in this order and in the programming it runs like a normal program.
With one of these "normal" sockets you would have to wait for all of
the data to return from the server in order to continue, right? It only
makes sense that you cannot execute any other code in the program until
this code to get the data returned has finished processing. Well
asynchronous sockets make it possible to continue code execution while
the data is being received. So in a nutshell, when talking about an
asynchronous socket: the socket is created, and the connection is
opened, the data is sent. At this point the code sort of branches off
on its own to finish getting the returned data and processing that,
meanwhile
The next line in our code is used to tell the socket object
(httpsocket) what function to call during the "receive" phase. The
receive phase occurs directly after we call the send() method (which
you will see in a minute). In this case looking at the code:
httpsocket.onreadystatechange=socketreceive;
We can see that our function "socketreceive" is set to be called
during the receive part of this process. After this our socket object
(httpsocket) is setup and ready to go, all that's left to do now is
actually send the data.
In the case of the XMLHttpObject the send() works a bit differently
than what you would expect (if you know anything about how a GET
request actually looks). To keep this simple I will offer you the
following explanation: If you're doing a POST request, the data you
need to send is passed in the send() function. If you are simply doing
a GET request there is no data to actually send, so we will send
nothing or null, depending on our browser type (remember creating the
object we had to determine whether or not we are using IE or Firefox).
Well, this holds true for the send() method as well. Let's look at the
code:
if(window.XMLHttpRequest)
httpsocket.send(null);
else if(window.ActiveXObject)
httpsocket.send();
When the data is returned from the script (ajax.php), it is passed
to whatever we set as the "onreadystatechange" value of our socket
object (httpsocket). That is the next function we will be looking at in
our code. In our case the function name is "socketreceive", as you
might remember from:
httpsocket.onreadystatechange=socketreceive;
Our code for this function is:
function socketreceive() {
if(httpsocket.readyState==4) {
if(httpsocket.status==200 || httpsocket.status==304) {
document.getElementById('received').innerHTML=httpsocket.responseText;
}
}
}
The first line of code in this function is a quick check to see what
the "readyState" value in our socket object is. The "readyState" value
tells us what part of the connection we are at. There are 5 possible
values for readyState that represent the 5 states of the connection.
They are as follows:
- 0 - uninitialized (the socket has not been connected)
- 1 - the open connection method has been called
- 2 - data has been sent
- 3 - it is getting data back from the server
- 4 - it has all data back from the server
In our receive function we only want to deal with the socket after
all of the data has been returned. So of course we would check to make
sure that the "readyState" value is a 4 before attempting to gather all
data. Some things that may be useful for the other "readyState" values
would be creating a progress bar on the page and incrementing it as the
value of "readyState" does. There are many other things they can be
used for to help debug your web applications or let the user know
what's happening while they are waiting for new information to load on
the page.
If the "readyState" value is 4 this means all of the data has been returned, which leads us to our next line of code:
if(httpsocket.status==200 || httpsocket.status==304)
To further ensure that the data returned will be accurate we need to
check the "status" value in our socket. This has nothing to do with our
actual socket or where it is at as far as send/receive goes, but has
more to do with the actual data returned. In HTTP there are numerous
status codes, some of which have probably seen either in normal web
surfing or in other programming projects. A few examples are:
- 200 - OK
- 304 - Not Modified
- 404 - Not Found
- 500 - Internal Server Error
404 is probably one that everyone has seen, so you know what I'm
talking about with these "codes". In our javascript we are checking to
be sure that a 200 or a 304 is returned as the "status" value. This
"status" code is determined by whatever page we were sending the
request to, in this case: ajax.php.
If the ajax.php file executed correctly, you should get back a 200
OK from our request and therefore this if/then statement is true. The
304 has to do with browser caching and is a bit more in depth than I'm
willing to go in this article. For your own sake, just do some research
into HTTP Status Codes and learn about them. You will need to at some
point anyway if you're considering doing any serious web coding.
At this point we have verified that all the data is returned using
our "readyState", we have also verified that the data returned is good
using the "status" value. The only thing left to do here is grab the
text received and actually do something with it. This "something" can
be anything you like, but in our case we are just going to print it out
in a "div" to show it on the page. I will let you dream up the other
possibilities, but in our code the returned data is shown on the page
with this line of code:
document.getElementById('received').innerHTML=httpsocket.responseText;
The first portion simply grabs our div element "received" and tells
it to set the innerHTML of it to whatever is stored in
httpsocket.responseText. The "responseText" value holds the data that
was returned by the server.
I hope by now you have a much better understanding of how a very
simple and basic ajax request is made using javascript and php. Stay
tuned, this is only the first part of a multi-part tutorial on ajax.
The next article will discuss using multiple socket objects to execute
multiple requests at once. "Why?", you might ask. Well, consider that a
user clicks the button on our script and creates the httpsocket. Then
before the data is returned the button (or another button) is clicked
that uses ajax as well. Well, a dilemma is created here because the
httpsocket object for the first click is over-written with the values
of the new click, and the send/receive that was supposed to occur for
the first click never actually finishes. In most applications data will
be returned so quickly that this would never happen, but you should
implement it anyway as a fail safe to optimise user experience. The
article will be linked here at the bottom after it is posted, so
bookmark this post if you would like to check it periodically for the
new part to this series.
|