Still worrying about mastering Ajax? Read this article and you will find all the answers for Ajax
JS series 8.0 is mainly AJAX summary and practice,this article describes the basic knowledge of Ajax in detail, including basic Ajax requests, encapsulation of Ajax requests, request data format issues, status codes, etc. In addition, it also involves cross-domain issues and implementation issues of Ajax interceptors, and cites specific examples to deepen understanding study
1 Overview
- Ajax It is a set of methods provided by the browser, which can update data without refreshing the page, and improve the experience of users browsing website applications.
-
Application scenarios:
- Pull up the page to load more data
- no refresh pagination
- Form item out of focus data validation
- Search box prompt text drop-down list
-
Disadvantage: Ajax itself does not support cross-domain requests
2. The basic process of ajax request
var xhr = new XMLHttpRequest();
xhr.open('method','url',async(can be omitted));
xhr. send();
xhr.onload = function (){}
2.1 Create ajax object
var xhr = new XMLHttpRequest()
2.2 Set Request
xhr.open(method,url,async)
: ajax request method: get or post, and the request address url, whether it is asynchronous async (default is true) and it is not recommended to change async to false, the user experience will be very bad difference
Use post request
Note: If you use the post method, you must set the parameter format type of the request, .setRequestHeader(header, value)
header: The name of the attribute.
value: The value of the attribute.
httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
When using setRequestHeader() after open(), before send()
Place the request parameters in different positions when making an Ajax request: put the get behind the request address, and put the post in the send method
Send form type data:
('Content-Type', 'application/x-www-form-urlencoded')
Data format: name=Xiaoming&age=20
xhr.send('username=admin&age=18')
Send data of JSON type: (to convert the json object to json string, because the request parameters must be passed in string format)
('Content-Type', 'application/json')
Data format: {name: 'Xiao Ming', age: '20'}
xhr.send(JSON.stringify({name: 'admin', age:18}));
2.3 Send request
xhr.send()
2.4 Get the data from the server to the client
xhr.onload = function (){
console.log(xhr.responseText)
// xhr.responseText receives response data in text format
// xhr.responseXML receives response data in xml format
}
3. Data format
3.1 JSON. parse()
-
In the process of http request and response, whether it is the request parameter or the response content, if it is an object type, it will eventually be converted into object string for transmission, so
JSON.parse() should be used to obtain
return to json objectJSON.parse() // convert json string to json object
3.2 JSON.stringify()
-
Note: the get request cannot submit the json object data format, it must be converted into a json string
JSON.stringify() // convert json object to json string
Number Infinity and NaN and value null will be converted to null when using JSON.stringify()
JSON.stringify([NaN, null, Infinity]); // '[null,null,null]'
-
JSON.stringify() and localStorage access
const session = { 'screens': [ { 'name': 'screenA', 'width': 450, 'height': 250 }, { 'name': 'screenB', 'width': 650, 'height': 350 }, { 'name': 'screenC', 'width': 750, 'height': 120 } ], 'state': true }; localStorage.setItem('session',JSON.stringify(session) ); const restoredSession = JSON.parse(localStorage.getItem('session')); console.log(restoredSession);
If you don't use JSON.stringify() to save data and JSON.parse() to get data:
localStorage.setItem('session', session);
const restoredSession = localStorage.getItem('session');
console.log(restoredSession);
If you do not use JSON.parse() to fetch data when fetching data
localStorage.setItem('session', JSON.stringify( session));
const restoredSession = localStorage.getItem('session');
console.log(restoredSession);
If JSON.stringify() is not used when saving data, an error will be reported
4. Ajax status code
- 0: the request is uninitialized (open() has not been called yet)
- 1: Loading: server connection established but not yet sent (open has been called, send() has not been called yet)
- 2: The request has been sent and loaded
- 3: The request is being processed, usually some data is already available in the response
- 4: The response has been completed, and the response from the server can be obtained and used
xhr.readyState // get Ajax status code
xhr.onprogress
is when the status code is 3, you can write loading animation and other effects at this time, such as the small dot loading when the page jumps, xhr.onprogress is a non-required function
xhr.onprogress = function(){
console.log('READYSTATE: ', xhr.readyState);
}
Common status codes
- 200 indicates that the request sent from the client is processed normally on the server side
- 204 indicates that the request was processed successfully, but no resources were returned.
- 301 means a permanent redirect. This status code indicates that the requested resource has been assigned a new URI and that the URI to which the resource now refers should be used in the future.
- 302 indicates a temporary redirect.
- 401 means Unauthorized, the current request requires user authentication
- 403 means the server rejected the request
- 404 means the server could not find the requested page
- 503 means the server is temporarily overloaded or under maintenance and unable to process the request.
5. The difference between onreadystatechange event and onload event
onreadystatechange :
When the Ajax status code changes, the onreadystatechange event will be triggered automatically. When the status code is 4, the server-side response data can be obtained through xhr.responseText
.
// When the Ajax status code changes
xhr.onreadystatechange = function () {
// Judge when the Ajax status code is 4
if (this. readyState == 4 && this. status == 200) {
// Get the response data from the server
console.log(xhr.responseText);
}
}
Use onreadystatechange to print status code 2, 3, 4
onload:
Only when it is in status code 4, that is, when the response is ready, it will enter onload. Using onload only prints status code 4
6. Ajax error handling
xhr.onerror = function () {
alert('Ajax request error')
}
//This event is triggered when the request encounters an error
- The network is smooth, the server can receive the request, but the result returned by the server is not the expected result. Use
xhr.status
to get the http status code for troubleshooting - The network is smooth, the server does not receive the request, and returns a 404 status code: check whether the request address is wrong.
- The network is smooth, the server can receive the request, and the server returns a status code of 500: server error, and communicate with the back-end programmer.
7. Ajax example application
Note: If you use a local file to debug ajax, you can use open with live server to open it, otherwise an error will be reported, because the browser thinks this method is not safe, and it will be regarded as a cross-site attack and will block the request
Recommend an ajax interface website that can request data for free for testing: FillText.com
7.1 ajax get plain text
<button id="button">get plain text</button>
<br><br>
<div id="text"></div>
<script>
document.getElementById('button').addEventListener('click', loadText);
function loadText(){
var xhr = new XMLHttpRequest();
xhr.open('GET', 'sample.txt');
xhr.onload = function(){
console.log('READYSTATE: ', xhr.readyState);
if(this.status == 200){
document.getElementById('text').innerHTML = this.responseText;
} else if(this.status = 404){
document.getElementById('text').innerHTML = 'Not Found';
}
}
xhr.onerror = function(){
console.log('request error');
}
xhr.send();
}
</script>
If you change to a text file that does not exist, an error will be reported
xhr.open('GET', 'sample2.txt');
7.2 ajax get local JSON file
<body>
<button id="button">Get Users</button>
<h1>Users</h1>
<div id="users"></div>
<script>
document.getElementById('button').addEventListener('click', loadUsers);
function loadUsers() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'users.json');
xhr.onload = function () {
var users = JSON.parse(this.responseText);
var output = '';
for (var i in users) {
output += `
<ul>
<li>ID:${users[i].id}</li>
<li>Name: ${users[i].name}</li>
</ul>
`;
}
document.getElementById('users').innerHTML = output;
};
xhr.send();
}
</script>
</body>
JSON file:
[
{
"id":1,
"name":"Rick"
},
{
"id":2,
"name":"Wang"
},
{
"id":3,
"name":"Fang"
}
]
7.3 ajax get external link api
<script>
document.getElementById('button').addEventListener('click', loadUsers);
function loadUsers(){
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://www.filltext.com/?rows=6&fname={firstName}&lname={lastName}');
xhr.onload = function(){
var users = JSON.parse(this.responseText);
console.log(users);
var output = '';
for(var i in users){
output +=
'<div class="user">' +
'<ul>' +
'<li>fname: '+users[i].fname+'</li>' +
'<li>lname: '+users[i].lname+'</li>' +
'</ul>' +
'</div>';
}
document.getElementById('users').innerHTML = output;
}
xhr.send();
}
</script>
7.4 Using ajax in jquery
$('#btn').on('click', function () {
$.ajax({
type: 'post',
url: '',
// Request parameters sent to the server
data: JSON.stringify(params),
success: function (xhr) {
console. log(xhr);
}
})
});
8. ajax package
Object.assign(target, ...sources)
:
target: The target object, the object that receives the properties of the source object, is also the modified return value.
sources: The source object, containing the attributes that will be merged.
If the target object has the same key as the source object, the properties in the target object will be overwritten by the properties in the source object, and the properties of the later source objects will similarly override the properties of the previous source objects.
Package:
<script>
function ajax (options) {
// stores the default value
var defaults = {
type: 'get',
url: '',
data: {},
header: {
'Content-Type': 'application/x-www-form-urlencoded'
},
success: function () {},
error: function () {}
};
// Use the properties in the options object to override the properties in the defaults object
Object. assign(defaults, options);
var xhr = new XMLHttpRequest();
// Variables for splicing request parameters
var params = '';
// Circulate the parameters passed by the user, that is, the loop traversal and value of the object
for (var value in defaults. data) {
// convert the parameter to string format
params += value + '=' + defaults.data[value] + '&';
//value is the object attribute name, defaults.data[value] is the corresponding attribute value
}
// Intercept the & at the end of the parameter
params = params.substr(0, params.length - 1);
// Determine the request method
if (defaults. type == 'get') {
defaults.url = defaults.url + '?' + params;
}
// configure the ajax object
xhr.open(defaults.type, defaults.url);
// If the request method is post
if (defaults. type == 'post') {
// Set the type of request parameter format
var contentType = defaults. header['Content-Type']
//xhr.setRequestHeader after xhr.open, before xhr.send
xhr.setRequestHeader('Content-Type', contentType);
// if the type is json
if (contentType == 'application/json') {
xhr.send(JSON.stringify(defaults.data))
} else {
// Pass request parameters of common types to the server
xhr. send(params);
}
}
else {
// send get request
xhr. send();
}
// Triggered when the xhr object has received the response data
xhr.onload = function () {
// Get the data type in the response header
var contentType = xhr. getResponseHeader('Content-Type');
// The data returned by the server
var responseText = xhr. responseText;
// if the response type is json
if (contentType. includes('application/json')) {
// convert json string to json object
responseText = JSON. parse(responseText)
}
if (xhr. status == 200) {
// The request is successful Call the function that handles the success
defaults.success(responseText, xhr);
} else {
// The request failed, call the function that handles the failure
defaults.error(responseText, xhr);
}
}
// when the network is interrupted
xhr.onerror = function () {
// Call the failure callback function and pass the xhr object to the callback function
defaults. error(xhr);
}
}
</script>
use:
<body>
<script src="/js/ajax.js"></script>
<script type="text/javascript">
ajax({
url: '',
type: '',
success: function(data) {
console.log(data)
}
})
</script>
</body>
9. Cross-domain problem solving
- Cross-domain through jsonp
- Cross-Origin Resource Sharing (CORS)
- location.hash + iframe
- window.name + iframe cross domain
- postMessage cross-domain
- document.domain + iframe cross-domain
- nginx proxy cross-domain
- Nodejs middleware proxy cross-domain
- Cross-domain WebSocket protocol
I will write a blog post in detail later
10. Use ajax to implement interceptors
The interceptor setting allows us to do some things before sending a request or receiving a response, such as changing the data format of the response, or adding different configs according to different requests, etc. The request interceptor is the operation performed before the request is sent, such as setting whether a token is required; the response interceptor is the operation after receiving the response, such as setting the response failure jump through the status code, etc.
10.1. Native AJAX implementation interceptor
The send method needs to be changed, XMLHttpRequest.prototype.send
redefines the send function in its prototype.
const intercept = (method, url, requestCallback, responseCallback) => {
let xhr = new XMLHttpRequest();
// Modify the prototype's open and send methods to create request and response interceptors
let open = XMLHttpRequest.prototype.open;
let send = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.open = function () {
requestCallback();
open. call(this, method, url);
};
XMLHttpRequest.prototype.send = function () {
//Called when the Ajax status code changes
this.addEventListener('readystatechange', function () {
//The function called when the request is successful, or when other status codes can be set
if (this.readyState === 4 && this.status === 200) {
//Response interceptor, return useful data
let response = JSON. parse(this. responseText);
responseCallback(response. data);
}
});
send.apply(this, arguments); //Change the calling object of the send function
};
xhr.open();
xhr. send();
};
let foo = function () {
console.log('The operation of sending the request');
};
let fn = function (data) {
//The return value after processing the response data
console. log(data);
};
//use
intercept('get', 'https://reqres.in/api/products/4', foo, fn)
result:
The complete code of multiple ajax interceptors can be passed in: GitHub
10.2. Use JQ's ajax to implement the interceptor
You can call the api that comes with jQuery: $.ajaxSetup
and beforeSend
$.ajaxSetup({
url: 'https://reqres.in/api/users/3', //test interface, can be used directly
// This function will be run before the request is sent
beforeSend() {
console.log('Operation before sending the request');
},
dataFilter: function (data, type) {
data = JSON. parse(data);
console. log(data);
//Process the response data and directly return the useful data in the response data
return JSON. stringify(data. data)
},
success: function (data) {
//Get the data in the response data
console. log(data);
},
});
//Call ajax, you can pass in your own set url, type, success, error,
// But the default values of async, headers and other parameters have been changed by $.ajaxSetup()
$.ajax({
url: 'https://reqres.in/api/products/3'
});
The settings of the $.ajaxSetup() method will be applied to the global AJAX properties of the entire page
beforeSend : This event fires before the Ajax request starts, allowing you to modify the XMLHttpRequest object (like setting additional headers, etc.)
dataFilter: Function for processing raw response data of XMLHttpRequest. This is a pre-filter function to sanitize the response
complete: function to be called when the request is complete (after success and error callbacks are executed)