AJAX

AJAX stands for asynchronous JavaScript and XML although JSON format is currently much more common. The basic principle is that a browser calls some backend functionality using JavaScript HTTP client (the visitor does not have to be aware of this at all) and retrieves some data (originally XML but it can also be JSON, piece of HTML or just plain text). This data can be inserted into HTML page without its reload thanks to dynamic HTML technologies. Asynchronous means that the visitor is not blocked from other interaction with site during that HTTP request. There can even be multiple HTTP requests processed at once.

You can entirely override default behaviour of the web browser using JavaScript and AJAX – you can use it to submit forms, execute actions and retrieve results from backend. You can also use AJAX to collect information about the behaviour of the visitor.

XMLHttpRequest

This object is responsible for HTTP communication controlled by JavaScript. Its API allows you to open a HTTP connection and check its progress when it changes using an event handler.

Let’s create a very small and simple example – a calculator that just adds two integers. We need a PHP backend to provide results. This file can read parameters from query and returns JSON object instead of standard HTML.

calculate.php file:

<?php
if(isset($_GET["a"]) && isset($_GET["b"])) {
    //read inputs
	$res = intval($_GET["a"]) + intval($_GET["b"]);
	//set correct content type of response
	header("Content-Type: application/json");
	//send data as JSON
	echo json_encode(["result" => $res]);
} else {
    //something is wrong
	http_response_code(400);
}

You can check the functionality of this script by calling e.g. http://host.com/calculate.php?a=5&b=8. Of course you can add two numbers directly in JavaScript, just pretend that we are calling some super-special function that needs to be performed on the server.

And we need a JavaScript to talk with backend and deliver results into HTML page. The JavaScript code simply opens HTTP connection using GET method to calculate.php script with correct query parameters and waits for its response. If everything goes smooth, PHP returns HTTP code 200 and JSON data that can be parsed by JavaScript’s JSON library.

index.html file:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>Using AJAX</title>
    <script type="text/javascript">
		window.onload = function() {
			var a = document.getElementById("a");
			var b = document.getElementById("b");
			var btn = document.getElementById("btn");
			var res = document.getElementById("res");
			btn.onclick = function() {
                //create a HTTP request when clicked on button
				var request = new XMLHttpRequest();
				//observe HTTP status changes
				request.onreadystatechange = function () {
					if(this.readyState == XMLHttpRequest.DONE && this.status == 200) {
					    //when done and HTTP code is 200, update result
						var resObj = JSON.parse(this.responseText);
						res.innerHTML = resObj.result;
					} else if(this.readyState == XMLHttpRequest.DONE) {
						res.innerHTML = "Error!";
					}
				};
				//open connection and send data to PHP backend
				request.open("GET", "calculate.php?a=" + a.value + "&b=" + b.value);
				//starts HTTP request and the event handler declared before gets executed
				request.send();
			};
		};
    </script>
</head>
<body>
	<input id="a" type="number" value="5" />
	<input id="b" type="number" value="3" />
	<button id="btn">Calculate</button>
	<span id="res"></span>
</body>
</html>

Put both files into same directory and open index.html in your browser, fill the form and press button. You can try to open calculate.php too and pass query parameters to observe JSON output. You should feel the difference between reloading the whole page and just replacing piece of HTML dynamically – AJAX seems to be faster and it is unusual to see web page to change its content without reload.

The JavaScript code is quite long, it is because I did not use any library or helper interface. In real applications you usually try to write as few lines of code as possible. You can use a library like Axios, jQuery, HTTP interface embedded in a framework (Angular has one, React and Vue do not) or browser’s Fetch API to simplify the code.

Take a look into network console (under F12 key and switch to Network tab) and observe what your browser sends and receives when you press Calculate button – you can find more about debugging AJAX in another article. To view request parameters and response body click the HTTP request to calculate.php file (you can use XHR filter) and then select Parameters tab and Response tab. I used Firefox browser but Chrome developers tools are very similar.

console.log() output

console.log() output

Timer functions are often used to poll backend when you need to deliver “continuous” updates. A better solution is to use WebSocket but this is a bit more complicated and requires support of backend (PHP script cannot run longer than certain amount of time – usually 30 seconds).

Fetch API

Fetch API is a modern wrapper for asynchronous HTTP requests (it does not work in Internet Explorer). It has higher-level syntax than previously described XMLHttpRequest and is promise-based. You can read about promises in JavaScript article. Here is the same calculator example with Fetch API:

index-fetch.html file:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>Using AJAX</title>
    <script type="text/javascript">
        window.onload = function() {
            var a = document.getElementById("a");
            var b = document.getElementById("b");
            var btn = document.getElementById("btn");
            var res = document.getElementById("res");
            btn.onclick = function() {
                //create a HTTP request when clicked on button
                var request = new Request("calculate.php?a=" + a.value + "&b=" + b.value);
                fetch(request).then(function(response) {
                    response.json().then(function(data) {
                        res.innerHTML = data.result;
                    }, function() {
                        res.innerHTML = "Response error!";
                    });
                }, function() {
                    res.innerHTML = "Request error!";
                });
            };
        };
    </script>
</head>
<body>
<input id="a" type="number" value="5" />
<input id="b" type="number" value="3" />
<button id="btn">Calculate</button>
<span id="res"></span>
</body>
</html>

Check out this article for another simple Fetch API example and also for AJAX debugging tips.

Use init parameter of fetch() function to specify HTTP method and additional HTTP headers etc.

Cross origin requests and OPTIONS HTTP request

You are probably very excited about reading any possible HTTP resource in your JavaScript page and displaying useful information on you site (such sites are called mashups). It is not that simple. The HTTP request that is issued from website downloaded from http://mysite.com to http://notmysite.org is called cross origin request and web browsers have special policy to handle them. To protect web servers with popular information from stealing it or DoS/DDoS attacks, the browser first asks the server with HTTP OPTIONS request (like GET but different method) before issuing real AJAX request. If the OPTIONS request is turned down by the http://notmyhost.org, the AJAX request fails.

AJAX and CORS

This applies mostly for AJAX requests made by JavaScript (when you use XMLHttpRequest or fetch API). You can freely download images <img src="http://notmysite.org/..." alt="whatever">, CSS <link rel="stylesheet" href="http://notmysite.org/..."> (including fonts), JavaScripts <script type="text/javascript" src="http://notmysite.org/..."> etc. defined in source code of your HTML.

To overcome this, you have to build backend proxy – a simple script that performs the HTTP request on behalf of your frontend application (your JavaScript frontend then communicates with the proxy script). The consequence is that you use single IP address of the server, where the proxy script is uploaded, and the owner of target machine can block you easily (if he does not like you to download information from his site).

AJAX and CORS

You do not have to worry about cross origin requests if you downloaded the web site from the same server where you send AJAX requests.

You sometimes encounter CORS abbreviation in this context. It means Cross origin resource sharing.

Configuring server to allow cross origin requests

Cross origin requests are not allowed by default, to allow them, send these HTTP headers with the response to the OPTIONS request (or all HTTP requests). The Access-Control-Allow-Origin should contain hostname of the server, where the browser obtained the HTML a JS code which will communicate with your backend or * to allow everything.

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: PUT, GET, POST, DELETE, PATCH, OPTIONS

There are more headers that start with Access-Control-Allow-..., they define allowed additional headers for example. You can send custom HTTP response headers with header() function. In Slim framework, use this code as middleware of your application (usually defined in src/middleware.php):

$app->add(function ($req, $res, $next) {
  $response = $next($req, $res);
  return $response
    ->withHeader('Access-Control-Allow-Origin',
                 'http://mysite.com')    //or * to allow everything
    ->withHeader('Access-Control-Allow-Headers',
                 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
    ->withHeader('Access-Control-Allow-Methods',
                 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
});

Some installations of Apache web server also need to be configured to allow alternative HTTP methods. This configuration is for Apache 2.2.x and should be present in your .htaccess file:

<Limit GET POST PUT DELETE PATCH OPTIONS>
  Allow from all
</Limit>

You obviously have to be the owner of the server to allow cross origin request. Sometimes you just have to use the proxy script to obtain data and hope to not get banned (use server cache to minimise amount of requests).

Summary

AJAX is powerful technique which allows you to fetch or send data in the background. By doing this you can achieve much smoother user experience. On the other hand, you have to learn JavaScript to use AJAX and you are definitely breaking your application into more heterogenous modules by moving part of the functionality into JavaScript frontend.

Most modern applications resigned on backend templates and moved to full-featured standalone JavaScript frontend applications – this is called SPA.

New Concepts and Terms

  • AJAX
  • Cross origin requests
  • Fetch API