Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.
This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.
1. Create your own API
1.1 Classification of apis
- REST APIS: restful (Representational State Transfer layer State transformation)
- (1) The operation of SENDING a request for CRUD is determined by the request mode
- (2) Multiple operations can be performed on the same request path
- (3) The request method will use GET/POST/PUT/DELETE
- The REST API: restless
- (1) The request mode does not determine the REQUESTED CRUD operation
- (2) One request path corresponds to only one operation
- (3) Generally only GET/POST
1.2 Setting up REST APIS using JSON-server
1.2.1 What is jSON-server?
A toolkit for quickly building REST apis
1.2.2 using json – server
-
Online documentation: https://github.com/typicode/json-server
-
NPM install -g json-server
-
Create a database JSON file in the target root directory: db.json
{
"posts": [{"id": 1."title": "json-server"."author": "typicode" },
{ "id": 2."title": "json-server2"."author": "typicode"}]."comments": [{"id": 1."body": "some comment"."postId": 1}]."profile": { "name": "typicode"}}Copy the code
- Run the following command to start the server:
json-server --watch db.json
1.2.3 Using a browser to access the test
http://localhost:3000/posts
http://localhost:3000/posts/1
1.2.4 Using AXIOS to access tests
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div>
<button onclick="testGet()">A GET request</button>
<button onclick="testPost()">A POST request</button>
<button onclick="testPut()">PUT request</button>
<button onclick="testDelete()">The DELETE request</button>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js"></script>
<script>
function testGet() {
axios.get('http://localhost:3000/posts') // Return an array containing two objects
/ / axios. Get (' http://localhost:3000/posts/1 ') / / returns an object
// axios.get('http://localhost:3000/posts? Id =1') // Returns an array containing an object
.then(response= > {
console.log('/posts get', response.data)
})
}
function testPost() { // Add data
axios.post('http://localhost:3000/posts', {"title": "json-server3"."author": "typicode" })
.then(response= > {
console.log('/posts put', response.data)
})
}
function testPut() { // Update data
axios.put('http://localhost:3000/posts/3', {"title": "json-server_put"."author": "typicode" })
.then(response= > {
console.log('/posts post', response.data)
})
}
function testDelete() { // Delete data
axios.delete('http://localhost:3000/posts/3')
.then(response= > {
console.log('/posts delete', response.data)
})
}
</script>
</body>
</html>
Copy the code
2. Ajax encapsulation of XHR (simple version of Axios)
2.1 the characteristics of
- The return value of the function is
promise
The result of success isresponse
, the result of failure iserror
- Can handle multiple types of requests: GET/POST/PUT/DELETE
- The parameter to the function is a configuration object
{
url: ' '.// Request an address
method: ' '.// Request mode GET/POST/PUT/DELETE
params: {}, // GET/DELETE The query parameter of the request
data: {}, // POST/PUT Request body parameters
}
Copy the code
- The response JSON data is automatically parsed into JS objects/arrays
2.2 Coding Implementation
function axios({
url,
method='GET',
params={},
data={}
}){
// Return a Promise object
return new Promise((resolve, reject) = > {
// Handle method with uppercase
method = method.toUpperCase();
// Process the query argument (concatenated to the URL) id=1&xxx= ABC
let queryString = ' ';
Object.keys(params).forEach(key= > {
queryString += `${key}=${params[key]}& `
});
if(queryString){
// Remove the last '&'
queryString = queryString.substring(0, queryString.length-1)
/ / received a url
url += '? ' + queryString
}
// 1. Perform asynchronous Ajax requests
// Create an XHR object
const request = new XMLHttpRequest();
// Open the connection (initializes the request, no request)
request.open(method, url, true);
// Send the request
if(method === 'GET' || method === 'DELETE'){
request.send()// undefined
} else if (method === 'POST' || method === 'PUT') {// Set the request header to tell the server that the request body is in JSON format
request.setRequestHeader('Content-Type'.'appliaction/json; charset=utf-8');
// Send request parameters in JSON format
request.send(JSON.stringify(data)); // Execute asynchronously
}
// Bind the state change listener
request.onreadystatechange = function() { // Synchronize execution
// If the request is not completed, end it
if(request.readyState ! = =4) {
return;
}
// If the response status code is between [200, 300], it indicates success; otherwise, it fails
const {status, statusText} = request
if( status>= 200 && status<=299) {// 2.1 If the request succeeds, call resolve()
// Prepare the resulting data object response
const response = {
data: JSON.parse(request.response),
status,
statusText
};
resolve(response);
} else {Call reject() if the request fails
reject(new Error('request error status is '+ status)); }}})}Copy the code
2.3 Use Test
// 1. GET request: obtain data from the server
function testGet() {
axios({
url: 'http://localhost:3000/posts'.method: 'GET'.params: {id: 1.xxx: 'abc'
}
}).then(
response= > {
console.log(response)
},
error= > {
alert(error.message)
}
)
}
// 2. POST request: Add data to the server
function testPost() {
axios({
url: 'http://localhost:3000/posts'.method: 'POST'.data: {
"title": "json-server_post"."author": "typicode_post"
}
}).then(
response= > {
console.log(response)
},
error= > {
alert(error.message)
}
)
}
// 3. PUT request: The server updates data
function testPut() {
axios({
url: 'http://localhost:3000/posts/1'.method: 'PUT'.data: {
"title": "json-server_put"."author": "typicode_put"
}
}).then(
response= > {
console.log(response)
},
error= > {
alert(error.message)
}
)
}
// 3. DELETE request: the server deletes data
function testDelete() {
axios({
url: 'http://localhost:3000/posts/2'.method: 'delete'
}).then(
response= > {
console.log(response)
},
error= > {
alert(error.message)
}
)
}
Copy the code
3. Understanding and using axios
3.1 What is Axios?
- The most popular ajax request library on the front end
- React/Vue officially recommends using Axios to make Ajax requests
- Documents: https://github.com/axios/axios
3.2 axios characteristics
- Asynchronous Ajax request library based on XHR + Promise
- It can be used on both the browser and Node sides
- Support for request/response interceptors
- Support request cancellation
- Request/response data transformation
- Send multiple requests in batches
3.3 Axios Common syntax
-
Axios (config): generic/essential way to send any type of request
-
Axios (url[, config]): You can specify only the URL to send a GET request
-
Axios.request (config): equivalent to axios(config)
-
Axios.get (url[, config]): sends a GET request
-
Axios.delete (url[, config]): sends a DELETE request
-
Axios. post(URL [, data, config]): sends a POST request
-
Axios. put(URL [, data, config]): sends a PUT request
-
Axios.defaults. XXX: Default global configuration for requests (method\baseURL\params\timeout…)
-
Axios. Interceptors. Request. Use () : add request interceptor
-
Axios. Interceptors. Response. Use () : add response interceptors
-
Axios.create ([config]): Creates a new axios(it does not have the following functionality)
-
Axios.cancel (): Used to create an error object to Cancel the request
-
Axios.canceltoken (): The token object used to create the cancellation request
-
Axios.iscancel (): Whether it was an error to cancel the request
-
Axios.all (Promises): For batch execution of multiple asynchronous requests
-
Axios.spread (): Method used to specify the callback function that receives all success data
3.4 Understanding and use of difficult grammar
3.4.1 trackaxios.create(config)
-
A new AXIOS is created based on the specified configuration, that is, each new AXIOS has its own configuration
-
The new Axios just doesn’t have a way to cancel requests or batch them, and everything else is the same syntax
-
Why was this syntax designed?
(1) Requirements: The configuration of some interfaces in the project is different from that of other interfaces, how to deal with it (for example, multiple baseURL needs to be specified)
(2) Solution: Create two new AXIos, each with its own unique configuration, to be applied to interface requests with different requirements
const instance = axios.create({ // instance is a function type
baseURL: 'http://localhost:3000'
})
// Use instance to send Ajax requests
instance({
url: '/posts'
})
instance.get('/posts')
Copy the code
3.4.2 Call order of interceptor function/Ajax request/request callback function
- Description: Call
axios()
Instead of sending the Ajax request immediately, you need to go through a longer process - Flow: Request interceptor 2 => Request interceptor 1 => send ajax request => respond to interceptor 1 => respond to interceptor 2 => callback of the request
- Note: This flow is strung together by promises, which the request interceptor passes
config
The response interceptor passes isresponse
// Add two request interceptors (callback functions)
axios.interceptors.request.use(
config= > {
console.log('request interceptor1 onResolved()') / / -- -- -- -- -- -- -- -- -- -- - 2
return config
},
error= > {
console.log('request interceptor1 onRejected()')
return Promise.reject(error)
}
)
axios.interceptors.request.use(
config= > {
console.log('request interceptor2 onResolved()') / / -- -- -- -- -- -- -- -- -- -- - 1
return config
},
error= > {
console.log('request interceptor2 onRejected()')
return Promise.reject(error)
}
)
// Add two response interceptors
axios.interceptors.response.use(
resopnse= > {
console.log('response interceptor1 onResolved()') / / -- -- -- -- -- -- -- -- -- -- - 3
return resopnse
},
error= > {
console.log('response interceptor1 onRejected()')
return Promise.reject(error)
}
)
axios.interceptors.response.use(
resopnse= > {
console.log('response interceptor2 onResolved()') / / -- -- -- -- -- -- -- -- -- -- - 4
return resopnse
},
error= > {
console.log('response interceptor2 onRejected()')
return Promise.reject(error)
}
)
axios.get('http://localhost:3000/posts')
.then(response= > {
console.log('data', response.data) //data Array(4) -------------5
})
.catch(error= > {
cosole.log('error', error.message)
})
// request interceptor2 onResolved()
// request interceptor1 onResolved()
// response interceptor1 onResolved()
// response interceptor2 onResolved()
// data Array(4)
Copy the code
3.4.3 Canceling a Request
1. Basic process
- configuration
cancelToken
object - The cache is used to cancel the request
cancel
function - Called later at a specific time
cancel
Function cancel request - Determine if in error callbacks
error
是cancel
And do the corresponding processing
2. Implement functions
With Express, set up a server with latency
const express = require('express')
const cors = require('cors')
const app = express()
// Use CORS to allow cross-domain
app.use(cors())
// Can parse urlencode post request body parameters
app.use(express.urlencoded())
// Parse request body parameters in JSON format
app.use(express.json())
app.get('/products1'.(req, res) = > {
setTimeout(() = > {
res.send([
{id: 1.name: 'product1.1'},
{id: 2.name: 'product1.2'},
{id: 3.name: 'product1.3'}}]),1000 + Math.random()*2000);
})
app.get('/products2'.(req, res) = > {
setTimeout(() = > {
res.send([{
id: 1.name: 'product2.1'
},
{
id: 2.name: 'product2.2'
},
{
id: 3.name: 'product2.3'}}]),1000 + Math.random() * 2000);
})
app.listen(4000.() = > {
console.log('server app start on port 4000')})Copy the code
- Click the button to cancel a request in progress
let cancel // The function used to save the cancellation request
function getProducts1() {
axios({
url: 'http://localhost:4000/products1'.cancelToken: new axios.CancelToken(function executor(c){ // c is the function used to cancel the current request
// Save the cancel function, which may need to cancel the current request later
cancel = c;
})
}).then(
response= > {
cancel = null
console.log('Request 1 is successful', response.data)
},
error= > {
cancel = null
console.log('Request 1 failed', error.message, error) // Request 1 failed force Cancel request Cancel {message: "force Cancel request "}})}function getProducts2() {
axios({
url: 'http://localhost:4000/products2'
}).then(
response= > {
console.log('Request 2 is successful', response.data)
}
)
}
function cancelReq() {
// alert(' cancel request ')
// Execute the function to cancel the request
if (typeof cancel === 'function'){
cancel('Force cancel request')}else {
console.log('No cancelable request')}}Copy the code
- Before requesting an interface, cancel a previous incomplete request
let cancel // The function used to save the cancellation request
function getProducts1() {
// Cancel pending requests before you are ready to send them
if (typeof cancel === 'function'){
cancel('Cancel request')
}
axios({
url: 'http://localhost:4000/products1'.cancelToken: new axios.CancelToken(function executor(c){ // c is the function used to cancel the current request
// Save the cancel function, which may need to cancel the current request later
cancel = c;
})
}).then(
response= > {
cancel = null
console.log('Request 1 is successful', response.data)
},
error= > {
if (axios.isCancel(error)){
console.log('Error requesting 1 to cancel', error.message)
}else{ // The request is in error
cancel = null
console.log('Request 1 failed', error.message, error) // Request 1 failed force Cancel request Cancel {message: "force Cancel request "}}})}function getProducts2() {
// Cancel pending requests before you are ready to send them
if (typeof cancel === 'function'){
cancel('Cancel request')
}
axios({
url: 'http://localhost:4000/products2'.cancelToken: new axios.CancelToken(function executor(c){
cancel = c;
})
}).then(
response= > {
cancel = null
console.log('Request 2 is successful', response.data)
},
error= > {
if (axios.isCancel(error)){
console.log('Error requesting 2 to cancel', error.message)
}else{
cancel = null
console.log('Request 2 failed', error.message, error)
}
}
)
}
function cancelReq() {
// alert(' cancel request ')
// Execute the function to cancel the request
if (typeof cancel === 'function'){
cancel('Force cancel request')}else {
console.log('No cancelable request')}}Copy the code
Use interceptors to improve code and reduce code duplication
// Add request interceptor
axios.interceptors.request.use((config) = > { // Write only one successful callback
// Cancel pending requests before you are ready to send them
if (typeof cancel === 'function'){
cancel('Cancel request')}// Add a cancelToken configuration
config.cancelToken = new axios.CancelToken(function executor(c){ // c is the function used to cancel the current request
// Save the cancel function, which may need to cancel the current request later
cancel = c;
})
return config
})
// Add a response interceptor
axios.interceptors.response.use(
response= > { // Successful callback
cancel = null
return response
},
error= > { // Failed callback
if (axios.isCancel(error)){ // Error requesting cancellation
console.log('Error requesting cancellation', error.message)
// Break the Promise chain
return new Promise(() = >{})}else{ // The request is in error
cancel = null
// Pass the error down
// throw error
return Promise.reject(error)
}
}
)
let cancel // The function used to save the cancellation request
function getProducts1() {
axios({
url: 'http://localhost:4000/products1'
}).then(
response= > {
console.log('Request 1 is successful', response.data)
},
error= > { // Only handle request failure, cancel request error is not handled
console.log('Request 1 failed', error.message, error)
}
)
}
function getProducts2() {
axios({
url: 'http://localhost:4000/products2'
}).then(
response= > {
console.log('Request 2 is successful', response.data)
},
error= > {
console.log('Request 2 failed', error.message, error)
}
)
}
function cancelReq() {
if (typeof cancel === 'function'){
cancel('Force cancel request')}else {
console.log('No cancelable request')}}Copy the code