Networking

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.

XMLHttpRequest Object (XHR)

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

Get and Post Requests

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.

Fetch API

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);

Websockets

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
};