Asynchronous Javascript XML or ajax for short is used to make requests to a server and retreiving data making changes to a web page without having to reload the entire page, for example lets say yo a a small section on your web page that looks at some stocks, periodically this section and only this section performs a ajax call to the stocks web site and retreives refreshed data and then updated this section only, this is what ajax does in simple terms.
The technology used is the XMLHttpRequest (XHR) object which is used to make server requests and evaluating the response. This is all done asynchronously using the XHR object, data is requested and returned and then inserted into the DOM.
All modern browsers use the XHR object, which can be created by using XMLHttpRequest(), you can then use the open() method to prepare a request that you will send to a server, then you use send() to actually request what you have asked for, when the server responds the XHR object is then populated with data and other properties are updated one which is important as it indicates the HTTP status of the request, 200 means its was successful, the other properties are below
There are a number of HTTP headers that contain various bits of information sent with every request and response
Here is a simple example of a XHR request
XHR example | let xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() {...} // you can use the onreadystatechange event handler, setup before open xhr.open("get", "getStocks.php", false); // types of data (get/post), URL, send asynchronously (true or false) xhr.setRequestHeader("MyHeader", "MyValue"); // send you own header and value which the serer can use xhr.send(null); let myHeader = xhr.getResponseHeader("MyHeader"); // retrieve a specific header from the response let allHeaders xhr.getAllResponseHeaders(); // retrieve all headers from the response |
XMLHttpRequest Level 2 added new features to improve the current XMLHttpRequest, firstly FormData was added to make serialization of forms easier, also a timeout property was added so to abort the request after a sepcified period, lastly the overrideMimeType was added to override the MIME type of an XHR response
XMLHttpRequest Level 2 examples | let form = document.getElementById("user-info"); let xhr = new XMLHttpRequest(); xhr.open("get", "getStocks.php", true); xhr.overrideMimeType("text/xml"); xhr.timeout = 5000; // set timeout for 5 seconds xhr.ontimeout = function() { alert("Request is taking too long, aborted after 5 seconds."); }; xhr.send(new FormData(form)); Note: there is also onload and onprogress events that you can use as well |
A GET request generally is a simple request of data from a server, you can pass query arguments along with the URL which the server can be use to find specific data,
Get request with arguments | xhr.open("get", "getStocks.php?name1=gsk&name2=azn", true); // you can use a variable for the URL stocksURL = "getStocks.php?name1=gsk&name2=azn" xhr.open("get", stocksURL, true); |
Post Requests generally send data along with the request for example a form is a good example of a POST request, the data is stored in the body of the request which can contain large amounts of data that can be in any format for example JSON.
Post request | xhr.open("post", "placeStockBid.php", true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); let stockForm = document.getElementById("user-info"); xhr.send(serialize(stockForm)); // stockForm may contain large amount of data |
Cross-Origin Resource Sharing (CORS)
As web browser tighten security you will see this type of error more, basically XHR ojects can only access on the domain from which the web page originates, this additonal security feature prevents some malicious behavior.
Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell browsers to give a web application running at one origin, access to selected resources from a different origin. A web application executes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, or port) from its own. A origin header would be Origin: http://www.domainx.com, if the server decides the request should be allowed it send back a Access-Control-Allow-Origin: "*" back, if the header is missing or don't match then the request is rejected, you can see this in the below diagram. When testing there are things that you can set in the browser to turn off CORS checking.
You can use custom headers for CORS which is called preflighted requests which is an advanced feature
There is lots more to learn regarding CORS and secruity and will leave you to the internet to dive deeper.
The newer Fetch API does the same as XHR but makes things easier, one difference is that all requests by the Fetch API are strictly asynchronous, you use the fetch() method to retrieve data and a promise is returned, there are many options that you can use like method, headers, body, cache, credentials, keepalive, etc.
Fetch example | // This does look better than the XHR solution above const data = { stock: 'gsk' }; fetch('https://datadisk.co.uk/getStocks.php', { method: 'POST', // 'GET' or 'PUT', etc headers: { // you can add headers 'Content-Type': 'application/json', }, body: JSON.stringify(data), // the payload }) .then(response => response.json()) .then(data => { console.log('Success:', data); }) .catch((error) => { // catching errors is easy console.error('Error:', error); }); |
There are three objects that you can use with Fetch called Headers, Request and Response, both of which have many options
Request object examples | let r = new Request('https://foo.com', { method: 'POST', body: 'foobar' }); fetch(r); |
Not all Javascript applications involve the web you may write an internal chat application and this is were websockets may be handy, it is used when you want to provide a long lasting connection between a server and a client, it uses the HTTP protocol to start the communication and then switches to use the Web Socket Protocol (WSP), and thus the URL uses a ws:// instead of a traditional http:// or https://, this protocol is designed for handling small amonts of data.
You create a websocket using the Websocket constructor and passing the URL that will provide the connection, there is a readyState property that indicates the current state
WebSocket examples | let socket = new WebSocket("ws://www.datadisk.co.uk/getStocks.php"); let stringData = "gsk"; let arrayBufferData = Uint8Array.from(['f', 'o' 'o']); let blobData = new Blob(['f', 'o' 'o']); // we can send different types of data socket.send(stringData); socket.send(arrayBufferData.buffer); socket.send(blobData); // server has an event handler onmessage (other event handlers are onopen, onclose, onerror) socket.onmessage = function(event) { let data = event.data; // do something with data }; |