Asynchronous applications AJAX, XMLHttpRequest

Synchronous applications

Action → Request → HTML response → Action → …

  1. The user queries a URL

    GET /action?parameters HTTP/1.1
    ...
    
  2. The servers replies with some HTML.

  3. The user leaves the page by one of the following:

    • Clicking a link,
    • Clicking a submit button,
    • reloading the page.
    POST /other_action?parameters HTTP/1.1
    ...
    
  4. The server replies with more HTML.

And the state?

HTTP is stateless

In so-called Web 1.0 apps, the server is the only one responsible for keeping the state

  • In the application logic (URLs, requests, etc.);
  • In its local storage (sessions, databases);
  • On the client (cookies).

Action → Request → HTML response → …

Collateral damage: the browser looses the state (except for its local storage) at each new action.

Demonstration: surf to some other page, then come back.

Time spent on these slides:

Synchronous browsing

Description of the Web 1.0 dataflow model, by Jesse J
Garret

Synchronous example

Ask StackOverflow:

<form method='GET' action='http://stackoverflow.com/search'>
  
  <input name='q' type='text' value='AJAX' />
  <input type='submit' value='Ask' />
</form>

Asynchronous browsing

Description of the AJAX dataflow model, by Jesse J Garret

Asynchronous example

Ask StackOverflow:

Asynchronous browsing

What is needed for asynchronous browsing?

Action ≠ Request

  • JavaScript intercepts user actions (events).

Asynchronous requests (XMLHttpRequest, Fetch API)

  • JavaScript can initiat a request independently from the user actions,
  • Requests do not interrupt browsing.

Server push (EventSource, Web sockets)

  • The server can send data to the client without waiting for a request.

XMLHttpRequest

Introduced by Microsoft in IE5, now a W3C standard.

  • Sends POST or GET (and more) requests to the server;
  • Does not block browser while waiting for the response.
  • Runs an asynchronous callback when it receives the response.
/***************  Click !  ***************/
mydiv.onclick = function() {
  var xhr = new XMLHttpRequest();
  xhr.open("GET", "../LICENSE");
  xhr.onload = function(event) {
    alert(xhr.response);
  }
  xhr.send();
}

Creation and preparation

var xhr = new XMLHttpRequest();
xhr.open("POST", "http://.../action?params");

Callbacks

xhr.onload = function(event) {
  console.log('Success');
}
xhr.onerror = function(event) {
  console.log('Error');
}
xhr.onabort = function(event) {
  console.log("Canceled by the user");
}
xhr.onprogress = function(event) {
  console.log('Downloading...');
}

Sending data

xhr.setRequestHeader('Content-Type', 'text/plain')
xhr.send("Hello world !");

Emulating a form (can also send binary data)

var formData = new FormData();
formData.append('q', 'AJAX');
formData.append('hl', 'en');
// Content-Type: multipart/form-data  by default
xhr.send(formData);

Sending JSON

var data = { primes : [2, 3, 5, 7],
             even   : [2, 4, 6, 8] };
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));

Reading the response

xhr.onload = function() {
  console.log(xhr.responseText);  // Simple text
  console.log(xhr.responseXML);   // XML (if the response is indeed XML)
  console.log(xhr.response);      // Configurable (text by default)
}

Pre-parsing the response

xhr.responseType = "json";
xhr.onload = function() {
  var obj = xhr.response;         // transformed to a JavaScript object
  console.log(obj.toto);          // by the browser
}
  • responseType = "text": text (default),
  • responseType = "document": DOM tree of a HTML document,
  • responseType = "arraybuffer", responseType = "Blob": binary data.

Case study: StackOverflow API

document.querySelector('#SO').onsubmit = function(e) {
var query = encodeURIComponent(document.querySelector('#query').value);
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.stackexchange.com/2.2/search/advanced' + '?q=' + query + '&site=stackoverflow');
xhr.onload = callback;
xhr.responseType = 'json';
xhr.send();
e.preventDefault();
}
  • Extracting input field data;
  • Escaping special characters;
  • Preparing the request for https://api.stackexchange.com;
  • Waiting for a JSON-formatted response;
  • Preventing form submission.

Case study: StackOverflow API

var callback = function(e) {
  if (xhr.response && xhr.response.items) {
    var liste = xhr.response.items;
for (var i = 0; i < liste.length; i++) { document.querySelector('#answers > ul').innerHTML = '<li>' + liste[i].title + '</li>'; }
} else { document.querySelector('#answers').innerHTML = '<p>Pas de résultats.</p>'; } }
  • The (JSON) response is converted to a JavaScript object;
  • Building a list of the questions corresponding to our search;
  • Inserting the result in the web page through the DOM;
  • See the full API documentation: https://api.stackexchange.com/docs/.

References

Fork me on GitHub