Reliable JavaScript Certification Online #

Ajax is an acronym for Asynchronous JavaScript and XML. It is a kind of approach in web applications architecture. Ajax is a technique of HTTP communication with a web server without reloading the web page. It results in a better user experience and makes web page more like web application. Ajax may be used as a result of user interaction to request data from the server or to save data to the server.
There are several ways of implementation Ajax. Historically, elements like img, iframe and script were used. Now commonly is used the XMLHttpRequest object type.

 

XMLHttpRequest object

XMLHttpRequest object type defines API for Ajax-style communication. It makes possible to send GET and POST requests and receive response from the server. XMLHttpRequest allows you to use not only XML format, but any text format is allowed. The XML part in XMLHttpRequest is historical legacy. Currently XML is rarely used in Ajax communication.

Sending the request

The first step of using XMLHttpRequest API is to create an instance of XMLHttpRequest object type.

var httpRequest = new XMLHttpRequest();

The second step is to call the open() method of XMLHttpRequest object and specify its required arguments: the HTTP request method and the URL being requested:

httpRequest.open('GET', 'getProducts');

The first argument is the HTTP request method. The method name is case-insensitive string however by convention it is usually written in uppercase letters. The “GET” method is usually used to get some data from the server and the URL specifies exactly requested resource. The “POST” method is usually used to post the form data, included in the request body. Other, rarely used methods are also “DELETE”, “PUT”, “HEAD”.

The second argument specifies the requested URL. It is relative to the document that contains script calling the open() method. If an absolute URL is specified, its protocol, domain and port must be generally the same as the document. Cross-origin requests normally cause an error and must be explicitly allowed by the server.

The third step of using XMLHttpRequest API is to define request headers. You should call the setRequestHeader, which as the first argument accepts the name of the hader and as the second argument the value of the header. For example POST requests require Content-Type header:

httpRequest.setRequestHeader('Content-Type', 'text/plain');

For security reason some headers cannot be defined programmatically and are set automatically, eg.: Content-Length, Referer, Cookie, Date.
The final step of making request is to specify the request body and send it to the server with the send() method. The request body is optional, you can omit it or pass null as the argument.

httpRequest.send(null);

The order of calling XMLHttpRequest object methods has matter and must be done in the order as described above.

var httpRequest = new XMLHttpRequest();
httpRequest.open('POST', 'message');
httpRequest.setRequestHeader(Content-Type', 'text/plain');
var body = 'A message for the server';
httpRequest.send(body);

Encoding the request body

Post form data

When the data from the HTML form is submitted, it is encoded into a string and sent to the server. By default form is sent using POST method and form data is the body of the request.
Similarly you can encode data in your Ajax application. Encoded data is like URI: a string of name=value pairs separated with ampersands where special characters are replaced with hexadecimal escape codes.

var body = 'name=ProXBook&category=notebook&price=1200';

Sending such encoded form data requires a special MIME type setting:

httpRequest.setRequestHeader(Content-Type', 'application/x-www-form-urlencoded');

See below a full example:

var httpRequest = new XMLHttpRequest();

httpRequest.open('POST', 'addProduct');
httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
var body = 'name=ProXBook&category=notebook&price=1200';
httpRequest.send(body);

Send data with GET

Data can be sent to the server also using GET method. For example it is suitable for search filters. GET request does not use the request body. Instead of it you should use the query part of URL to send data:

var httpRequest = new XMLHttpRequest();
var url = 'getProduct' + '?name=ProXBook&category=notebook';
httpRequest.open('GET', url);
httpRequest.send(null);
// handling of receiving response

Uploading files

The XMLHttpRequest object allows you to pass the File object directly to the send() method. You can obtain File object from the files property of HTML input type=“file” element.

var upload = document.getElementById('upload');
var file = upload.files[0];
var httpRequest = new XMLHttpRequest();
httpRequest.open('POST', 'upload');
httpRequest.send(file);

When you want to post both file and other form data you must use a special content-type “multipart/form-data”. Data can be prepared using FormData object that contains key/value pairs:

var upload = document.getElementById('upload');
var file1 = upload.files[0];
var file2 = upload.files[1];
var name = document.getElementById('name');
var formData = new FormData();
formData.append('file1', file1);
formData.append('file2', file2);
formData.append('file1', name.value);
var httpRequest = new XMLHttpRequest();
httpRequest.open('POST', 'addData');
// content-type multipart/form-data is set automatically when you pass FormData object to the send() method
httpRequest.send(formData);

Send XML data

You can send data to the server encoded as an XML document. Pass an XML document object as the argument of the send() method:

var xml = document.implementation.createDocument("", "data", null); // create <data> element
var data = xml.documentElement;
var category = xml.createElement('category'); // create <category> element
data.appendChild(category);
category.appendChild(xml.createTextNode('notebook')); // add 'notebook' as a content
// xml document: <data><category>notebook</category></data>

var httpRequest = new XMLHttpRequest();
httpRequest.open('POST', 'addXmlData');
httpRequest.send(xml);

Send JSON data

In recent years, the most popular data exchange format is JSON. You can conver JavaScript object to JSON string using JSON.stringify() method:

var httpRequest = new XMLHttpRequest();
httpRequest.open('POST', 'addUser');
httpRequest.setRequestHeader('Content-Type', 'application/json');
var user = {name: 'Marc', surname: 'Smith'};
httpRequest.send(JSON.stringify(user));

Retrieving the response

The HTTP response consists of a status code, response headers and a response body.

The status you can get through the status property of XMLHttpRequest object that holds HTTP status in numerical form and the statusText property that holds it in textual form. An example of successful request is the status code 200 and “OK”, an example of unsuccessful request, when resource is not found, is the status code 404 and “Not Found”.

The response headers you can read using getAllResponseHeaders() method, or using getResponseHeader() to read specific header passing its name as an argument.

The response body is stored in two properties: the responseText property stores it in textual form and the responseXML property stores it as XML document.

Asynchronous responses

XMLHttpRequest object normally is used asynchronously. This means that the send() method ends immediately after sending the request and does not block the running of the next statements. The response is available after a certain time, when it is received.

To be notified when the response came you have to listen for readystatechange event on the XMLHttpRequest object. This event may be fired multiple times in the time between sending a request and receiving a response.

You should test the readyState property of the XMLHttpRequest object, to know whether the response is complete. The readyState property specifies the status of an HTTP request. The XMLHttpRequest object type defines possible values of the readyState:

Constant Value
UNSENT 0
OPENED 1
HEADERS_RECEIVED 2
LOADING 3
DONE 4

Below an example how to listen for the response of the XMLHttpRequest object request:

var callback = function(text) {
    alert(text);
}
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', 'getProduct/?id=1');
httpRequest.onreadystatechange = function() {
    if (httpRequest.readyState == XMLHttpRequest.DONE && httpRequest == 200) {
        callback(httpRequest.responseText);
    }
};
httpRequest.send(null);

Synchronous responses

Most often HTTP responses are handled asynchronously. However it is possible to handle them synchronously. The open() method of the XMLHttpRequest object has an optional, third parameter, indicating whether to perform the operation asynchronously. By default it is set to true. If you set it to false, operation is performed synchronously and the send() method does not return until the response is received. In this case you do not have to use an event handler, to know when the response is ready. Ones the send() method returns, you can access the response. An example of synchronous response below:

var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', 'getProduct/?id=1');
httpRequest.send(null);
if (httpRequest == 200) {
    alert(httpRequest.responseText);
}

Decoding the response

In Ajax communication the server responses usually are textual and appropriate MIME type is set. These responses you may handle in several ways.

You can treat a response as a plain text, then you just have to read the responseText property of XMLHttpRequest object. The value will be a plain text.

If the server sends structured data in the form of XML, you will retrieve it using the responseXML property of XMLHttpRequest object. The value will be an XML object.

Data may be sent by the server as a JSON encoded string. You retrieve it reading the value of the responseText property of XMLHttpRequest object and parse it by the JSON.parse method.

var httpRequest = new XMLHttpRequest();
var url = 'getProduct?id=1';
httpRequest.open('GET', url);
httpRequest.send(null);
httpRequest.onreadystatechange = function() {
    var xml = null, json = null, text = null;
    var contentType = httpRequest.getResponseHeader('Content-Type');
    if (httpRequest.readyState == 4 && httpRequest.status == 200) {
        if (httpRequest.responseXML && contentType.indexOf('xml') != -1) {
            xml = httpRequest.responseXML;
        } else if (contentType == 'application/json') {
            json = JSON.parse(httpRequest.responseText);
        } else {
            text = httpRequest.responseText;
        }
        // further code
    }
};

 

JSONP

Another way of HTTP communication is use the <script> element as an Ajax transport mechanism. You should set the src attribute of the <script> and insert it into the document. Then the web browser will generate GET request to download data from the specified URL.
This mechanism is useful as it is not the subject of the same origin policy. Request can be sent to other servers.
The response from the server is automatically executed by JavaScript interpreter.
The name JSONP is related to the fact that usually the response from the server takes the form of JSON-encoded data, that is automatically decoded and executed. Execution of a code that contains pure JSON data does not have any effect. That is why server-side script must pad the response by surrounding it with parentheses and prefixing it with the name of a JavaScript function that will be executed on client-side.
Instead of sending only JSON data like here:

{name: "Tom", surname: "Smith"}

The servers sends JSON-padded response:

handleUser({name: "Tom", surname: "Smith"})

The response is a JavaScript expression, that is automatically executed by JavaScript interpreter. The name of the handler function can be dictated by the server and then on client-side you have to implement JavaScript function with the same name. More flexible solutions allow you to sent the name of the handler function as the value of the query parameter eg. ?callback=handleUser.