AJAX

An overview,

background

  • When the user login function is enabled, the user’s profile picture cannot be displayed when the user enters an email address
  • Unable to implement user registration function, when the user enters a mailbox or user name prompt whether there is
  • The latest user messages cannot be viewed in real time when the message board function is implemented

Before that, we can make the browser make a request to the server to get the server data in the following ways:

  • Address bar to enter the address, press Enter, refresh
  • Href or SRC attribute for a particular element
  • The form submission

These are all scenarios that we cannot or cannot program in code (making a request to the server and receiving the response from the server)

A technical solution for web programming (sending requests and receiving responses) on the browser side, which allows us to get the latest content from the server directly through JavaScript without having to reload the page. Make the Web more similar to the desktop application user experience.

Summary of Application Scenarios

For every unknown technology, when we learn about it, our first reaction is under what circumstances?

  • Get data on demand
  • Verify user data
  • Automatically updates page content
  • Improve user experience, no refresh experience

Second, get started quickly

At the core of the AJAX API is an XMLHttpRequest type that all AJAX operations need to use.

The process of using AJAX can be analogous to how we normally visit a web page

1. Create an object of type XMLHttpRequest -- equivalent to opening a browser
var xhr = new XMLHttpRequest()
// 2. Open a connection to a url -- equivalent to entering the address in the address bar
xhr.open('GET'.'/time')
// 3. Send a request over the connection -- equivalent to enter or click access to send the request
xhr.send(null)
// 4. Specify the XHR state change event handler -- the equivalent of handling the rendered web page
xhr.onreadystatechange = function () {
  // XHR's readyState determines whether the response to this request is received
  if (this.readyState === 4) {
    // Get the response body of the response from XHR's responseText
    console.log(this.responseText)
  }
}
Copy the code

readyState

var xhr = new XMLHttpRequest()
console.log(xhr.readyState)
/ / = > 0
// Initializes the request proxy object

xhr.open('GET'.'/time')
console.log(xhr.readyState)
/ / = > 1
The open method has been called to establish a connection to a specific port on the server

xhr.send()

xhr.addEventListener('readystatechange'.function () {
  switch (this.readyState) {
    case 2:
      / / = > 2
      // The response header has been received

      // Can get the head
      // console.log(this.getAllResponseHeaders())
      console.log(this.getResponseHeader('server'))
      // But I haven't got the body yet
      console.log(this.responseText)
      break

    case 3:
      / / = > 3
      // The response body of the response packet is being downloaded. The response body may be empty or incomplete

      // The response body is not safe to handle here.
      console.log(this.responseText)
      break

    case 4:
      / / = > 4
      // All is OK (the entire response message has been downloaded completely)

      // The response body is processed here
      console.log(this.responseText)
      break}})Copy the code

Understanding the meaning of each state value leads to the conclusion that we generally execute the subsequent logic of the response when readyState is 4.

xhr.onreadystatechange = function () {
  if (this.readyState === 4) {
    // Subsequent logic......}}Copy the code

Follow the HTTP

XMLHttpRequest is essentially JavaScript’s way of sending HTTP requests in the Web platform, so the request we send is still an HTTP request, which also conforms to HTTP conventions:

// Sets the request line for the request message
xhr.open('GET'.'/time')
// Set the request header
xhr.setRequestHeader('Accept'.'text/plain')
// Set the request body
xhr.send(null)

xhr.onreadystatechange = function () {
  if (this.readyState === 4) {
    // Get the response status code
    console.log(this.status)
    // Get the response status description
    console.log(this.statusText)
    // Get the response header information
    console.log(this.getResponseHeader('Content-Type')) // Specify the response header
    console.log(this.getAllResponseHeaders()) // All response headers
    // Get the response body
    console.log(this.responseText) // In text form
    console.log(this.responseXML) // it is in XML format}}Copy the code

Reference links:

  • Developer.mozilla.org/zh-CN/docs/…
  • Developer.mozilla.org/zh-CN/docs/…

The specific use

A GET request

Usually during a GET request, parameters are passed through the? Parameter passing.

var xhr = new XMLHttpRequest()
// GET requests usually pass parameters using question marks
// We can pass data to the server by adding parameters to the request address
xhr.open('GET'.'/delete? id=1')
// Generally, there is no need to set the response body for GET requests. You can pass NULL or no response at all
xhr.send(null)
xhr.onreadystatechange = function () {
  if (this.readyState === 4) {
    console.log(this.responseText)
  }
}

// In general, URLS pass parameter data, while POST is usually business data
Copy the code

A POST request

During POST request, the request body is used to carry the data to be submitted.

var xhr = new XMLHttpRequest()
The first argument to the open method sets the request method
xhr.open('POST'.'/add')
// Set the content-type in the request header to Application /x-www-form-urlencoded
// The request size for the request is urlencoded for the server to receive data
xhr.setRequestHeader('Content-Type'.'application/x-www-form-urlencoded')
// Data that needs to be sent to the server can be sent as an argument to the send method
// Format: name=zhangsan&age=18
xhr.send('name=zhangsan&age=18')
xhr.onreadystatechange = function () {
  if (this.readyState === 4) {
    console.log(this.responseText)
  }
}
Copy the code

Synchronous and asynchronous

The third parameter to the xhr.open() method requires a bool that sets whether the request is executed asynchronously or not. The default value is true, and false can be passed if the request is executed synchronously:

console.log('before ajax')
var xhr = new XMLHttpRequest()
// The default third argument is true, which means that the execution is asynchronous
xhr.open('GET'.'/time'.true)
xhr.send(null)
xhr.onreadystatechange = function () {
  if (this.readyState === 4) {
    // The code here is executed last
    console.log('request done')}}console.log('after ajax')
Copy the code

If executed synchronously, the code gets stuck in xhr.send() :

console.log('before ajax')
var xhr = new XMLHttpRequest()
// Synchronization mode
xhr.open('GET'.'/time'.false)
// // Synchronously registers events before invoking Send. Otherwise, readyStatechange cannot be triggered
// xhr.onreadystatechange = function () {
// if (this.readyState === 4) {
// // The code here is executed last
// console.log('request done')
/ /}
// }
xhr.send(null)
// The response has been downloaded because the send method has been executed
console.log(xhr.responseText)
console.log('after ajax')
Copy the code

The XMLHttpRequest API to summarize

attribute

  • readyStateXHR status 4 The response body is received
  • statusGet status code
  • responseTextGets the response body in text format
  • responseXMLGets the response body in XML format
  • onreadystatechangeEvent that is emitted when the xhr.readyState property changes

methods

  • open(method, url, async)Set request mode, request path, synchronous false/ asynchronous true
  • send(requsetBody)Send a request (body)
  • setRequestHeader(key, value)Set the request header
  • getResponseHeader(key)Get the response header

Response data format

Question: What if I want the server to return complex data?

The question is what format the server sends the data in, and how that format is parsed in JavaScript on the client side.

The cache problem

Caching is a problem where multiple AJAX GET requests to the same URL GET the same result. Most browsers don’t have this problem anymore, except for the early Days of Internet Explorer

var xhr = new XMLHttpRequest()
xhr.open('GET'.'/time')
xhr.send(null)
xhr.onreadystatechange = function () {
  if (this.readyState ! = =4) return
  console.log(this.responseText)
  // => Get the same result every time
}
Copy the code

The solution

URL with time stamp

The trick is to make the browser think the address is different every time it requests it.

var xhr = new XMLHttpRequest()
xhr.open('GET'.'/time? t=' + Date.now())
xhr.send(null)
xhr.onreadystatechange = function () {
  if (this.readyState ! = =4) return
  console.log(this.responseText)
  / / = >
}
Copy the code
The server sets the response header

The server tells the client browser not to cache the current address through the response header in the HTTP response packet.

app.get('/time'.(req, res) = > {
  res.setHeader('Cache-Control'.'no-cache')
  res.setHeader('Pragma'.'no-cache')
  res.setHeader('Expires'.'1')
  res.send(Date.now().toString())
})
Copy the code

More often than not, this problem is solved by stamping in front end development, because it is controllable in front end.

Compatible with the plan

XMLHttpRequest has compatibility issues in older browsers (IE5/6) and can be replaced in another way.

var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
// XHR has the same members
Copy the code

Three, encapsulation

AJAX request encapsulation

/** * Send an AJAX request *@param  {String}   Url Request address *@param  {String}   Method Request method *@param  {Object}   Params request parameter *@param  {Function} Done What needs to be done after the request completes (delegate/callback) */
function ajax (url, method, params, done) {
  // Convert to uppercase for subsequent judgment
  method = method.toUpperCase()

  // Object format parameters are converted to urlencoded format
  var pairs = []
  for (var key in params) {
    pairs.push(key + '=' + params[key])
  }
  var querystring = pairs.join('&')

  var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')

  xhr.addEventListener('readystatechange'.function () {
    if (this.readyState ! = =4) return

    // Try to parse the response body in JSON format
    try {
      done(JSON.parse(this.responseText))
    } catch (e) {
      done(this.responseText)
    }
  })

  // If it is a GET request, set the URL question mark parameter
  if (method === 'GET') {
    url += '? ' + querystring
  }

  xhr.open(method, url)

  // If it is a POST request, set the request body
  var data = null
  if (method === 'POST') {
    xhr.setRequestHeader('Content-Type'.'application/x-www-form-urlencoded')
    data = querystring
  }
  xhr.send(data)
}

ajax('get'.'/getsomthing', { id: 123 }, function (data) {
  console.log(data)
})

ajax('post'.'/addsomthing', { foo: 'posted data' }, function (data) {
  console.log(data)
})
Copy the code

In the jQuery AJAX

JQuery has an Ajax-specific package that you need to pay attention to when you use it frequently.

Reference:

  • www.jquery123.com/category/aj…
  • www.w3school.com.cn/jquery/jque…

$.ajax

$.ajax({
  url: '/time'.type: 'get'.dataType: 'json'.data: { id: 1 },
  beforeSend: function (xhr) {
    console.log('before send')},success: function (data) {
    console.log(data)
  },
  error: function (xhr) {
    console.log(xhr)
  },
  complete: function (xhr) {
    console.log('request completed')}})Copy the code

Common options:

  • Url: request address
  • Type: request method, defaultget
  • DataType: dataType of server response
  • ContentType: request body contentType, defaultapplication/x-www-form-urlencoded
  • Data: Data that needs to be passed to the server, via the URL if GET or the request body if POST
  • Timeout: request timeout period
  • BeforeSend: Triggered before the request is initiated
  • Success: Triggered after the request is successful (response status code 200)
  • Error: The request fails
  • Complete: the request is triggered (whether successful or not)

$.get

GET Request shortcut

$.get(url, data, callback)
Copy the code

$.post

POST request shortcut

$.post(url, data, callback)
Copy the code

Global event handling

www.jquery123.com/category/aj…

Axios

Axios is the most widely used AJAX packaging library at present. Compared with jQuery, Axios has more powerful functions and more simple responsibilities, which will be specially introduced in the later stage.

axios.get('/time')
  .then(function (res) {
    console.log(res.data)
  })
  .catch(function (err) {
    console.error(err)
  })
Copy the code

Fourth, the XMLHttpRequest 2.0

HTML5 to the XMLHttpRequest type comprehensive upgrade, easier to use, more powerful

The response properties

onload / onprogress

var xhr = new XMLHttpRequest()
xhr.open('GET'.'/time')
xhr.onload = function () {
  // onload readyState => 4
  // Only when the request completes
  console.log(this.readyState)
}
xhr.onprogress = function () {
  // onprogress readyState => 3
  // Only when the request is in progress
  console.log(this.readyState)
}
xhr.send(null)
Copy the code

FormData

AJAX operations that previously could only submit strings can now submit binary data

Download binary data using XMLHTTPRequest

var xhr = new XMLHTTPRequest();
xhr.open("GET", url, true);
/ / set the responseType
xhr.responseType = 'arraybuffer';
xhr.addEventListener('load'.function() {
    if(xhr.status === 200) {
        console.log(xhr.response); // ArrayBuffer
        console.log(new Blob([xhr.response])); // Blob
    }
})
xhr.send();
Copy the code

Download using JQuery Ajax

Ajax does not support arrayBuffer or BLOB as its dataType. So we need to write a beforeSend handler:

// Ajax setup function
$.ajaxSetup({
    beforeSend: function(jqXHR, settings) {
        if(settings.dataType === 'binary') {
            settings.xhr().responseType = 'arraybuffer';
            settings.processData = false;
        }
    }
})

$.ajax({
    url: url,
    dataType: 'binary'.success: function(data) {
        console.log(data); // ArrayBuffer
        console.log(new Blob([data])); // Blob}})Copy the code

Upload a binary file

// Monitor progress API
xhr.upload.onload = function() {
	taskPanel.style.display = 'none';
}
xhr.upload.onloadstart = function() {
	taskPanel.style.display = 'block';
}
xhr.upload.onprogress = function(e) {
	// Continuously triggered during upload
    // console.log(e);
    taskProgressStatusdiv.innerHTML = (e.loaded / e.total).toFixed(2) + The '%';
    progressDiv.style.width = (e.loaded / e.total) + The '%';
}

    // The body of the request needs to be passed in as an argument to the send method
    // xhr.send('a=1&b=2');

    // formData: formData can be built from the built-in formData object in JS
    // https://developer.mozilla.org/zh-CN/docs/Web/API/FormData
    let fd = new FormData();
    // fd.append('a', 1);
    // fd.append('b', 2);
    fd.append('attachment', fileElement.files[0]);
    xhr.send(fd);
Copy the code

The pros and cons of Ajax

Ajax advantages

  1. The asynchronous mode improves user experience

  2. Optimized transfer between browser and server to reduce unnecessary data round-trip and reduce bandwidth usage

  3. Ajax runs on the client side, taking over some of the work that would have been done by the server, reducing the load on the server under a large number of users.

  4. Ajax can achieve asynchronous communication effect, realize local page refresh, bring better user experience; Obtain data on demand to save bandwidth resources.

Ajax shortcomings

  1. Ajax does not support the browser back button, so it costs a lot to implement the front and back functions under Ajax. May cause an increase in the number of requests cross-domain problem limits

  2. Security issues AJAX exposes the details of the server interaction.

  3. Search engine support is weak.

  4. Broke the exception mechanism of the program.

Get and POST

Get is generally used for query operations. The URL address has a limited length and the requested parameters are exposed in the URL address. If Chinese parameters are transmitted, they need to be encoded by themselves, resulting in low security.

The POST request is used to submit data without any restriction on the length of the data. The submitted data is stored in the HTTP request body and will not be leaked in the URL address.