What is Axios?
Axios is a promise based web request library that works with Node.js and browsers. It is isomorphic (that is, the same set of code can run in the browser and node.js). On the server side it uses the native Node.js HTTP module, while on the client side it uses XMLHttpRequests.
features
- Created from the browser
XMLHttpRequests
- from
node.js
createhttp
request - support
Promise
API - Intercept requests and responses
- Transform request data and response data
- Cancel the request
- Automatic conversion
JSON
data - The client supports defense
XSRF
The basic use
The installation
npm install axios
bower install axios
yarn add axios
// Use unpkg CDN
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
// Use jsDelivr CDN
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
Copy the code
The import
import axios from 'axios'
Copy the code
Send the request
axios({
url:'xxx'.// Set the address of the request
method:"GET".// Set the request method
params: {// Get requests use params for arguments, or data for post requests
type: ' '.page: 1
}
}).then(res= > {
// res is the data returned by the back end
console.log(res);
})
Copy the code
Use cases
Make a GET request
// Make a request to the user with the given ID
axios.get('/user? ID=12345')
.then(function (response) {
// Handle success
console.log(response);
})
.catch(function (error) {
// Handle error cases
console.log(error);
})
.then(function () {
// Always execute
});
// The above request can also be completed as follows (optional)
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.then(function () {
// Always execute
});
// Support async/await usage
async function getUser() {
try {
const response = await axios.get('/user? ID=12345');
console.log(response);
} catch (error) {
console.error(error); }}Copy the code
Make a POST request
axios.post('/user', {
firstName: 'Fred'.lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Copy the code
Initiate multiple concurrent requests
function getUserAccount() {
return axios.get('/user/12345');
}
function getUserPermissions() {
return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(), getUserPermissions()])
// then((results) => {//
// const acct = results[0];
// const perm = results[1];
// })
.then(axios.spread((acct, perm) = >{}));/ / write 2
Copy the code
In notation 2, axios.spread takes a function as an argument and returns a new function. The argument to the received argument function is the response returned for each request in the axios.all method.
Two, why to encapsulate
The AXIos API is so friendly that you can easily use it directly in your project.
As the project scale, however, if each initiate a HTTP request, will put these such as set the timeout time, set the request header, which is used to judge according to the project environment request address, error handling, etc., all need to write it again, this kind of repeated labor is not only a waste of time, and make the code redundancy increase, it is difficult to maintain. To improve code quality, you should re-wrap AXIOS in your project and reuse it.
Here’s an example:
axios('http://localhost:3000/api', {
// Configure the code
method: 'GET'.timeout: 1000.withCredentials: true.headers: {
'Content-Type': 'application/json'.Authorization: 'xxx',},transformRequest: [function (data, headers) {
returndata; }].// Other request configuration...
})
.then((data) = > {
// todo: start coding business logic code
console.log(data);
}, (err) = > {
// Error handling
if (err.response.status === 401) {
// handle authorization error
}
if (err.response.status === 403) {
// handle server forbidden error
}
// Other error handling.....
console.log(err);
});
Copy the code
If every page sent a similar request, it would be too tedious to write a lot of configuration and error handling.
At this point, we need to re-wrap AXIos to make it easier to use
Three, how to package
-
At the same time, you need to negotiate some conventions with the back end, request headers, status codes, request timeout……
-
Setting interface request prefixes: The prefixes need to be differentiated based on the development, test, pre-delivery, and production environments.
-
Request header: to achieve some specific business, must carry some parameters can be requested (such as: user information);
-
Status code: Performs different services according to the different status returned by the interface, which needs to be agreed with the back end.
-
Request method: according to get, POST and other methods for a re-encapsulation, more convenient to use
-
Request interceptor: Determines which requests are accessible based on the request header
-
Response interceptor: This is the execution of different services based on the status code returned from the back end
Set the interface request prefix
Node environment variables are used to distinguish between development, test, and production environments
if (process.env.NODE_ENV === 'development') {
axios.defaults.baseURL = 'http://dev.xxx.com'
} else if (process.env.NODE_ENV === 'production') {
axios.defaults.baseURL = 'http://prod.xxx.com'
// Differentiate the online test, pre-release, and official environments according to the custom Node environment variables
}
Copy the code
Proxy configuration
In local debugging, the vue project also needs to configure devServer to implement proxy forwarding in the vue.config.js file, so as to achieve cross-domain.
devServer: {
proxy: {
'/proxyApi': {
target: 'http://dev.xxx.com'.changeOrigin: true.pathRewrite: {
'/proxyApi': ' '}}}}Copy the code
In the React project, you need to configure proxies in the setupproxy. js file.
const { createProxyMiddleware } = require('http-proxy-middleware');
const options = (path, targetUrl) = > {
let devOptions = {
target: targetUrl,
changeOrigin: true.secure: true.// Set a proxy that supports HTTPS
};
// Whether to enable the local mock interface
if (process.env.IS_MOCK === '1') {
devOptions = Object.assign(devOptions, {
target: process.env.MOCK_URL,
pathRewrite: {[` ^${path}`] :`/mock/api/xxx${path}`,}}); }return devOptions;
};
module.exports = (app) = > {
if (process.env.NODE_ENV === 'development') {
if (process.env.IS_MOCK === '1') {
app.use(
'/',
createProxyMiddleware(
options('/', process.env.TEST_URL),
),
);
} else {
app.use(
'/api',
createProxyMiddleware(
options('/api', process.env.TEST_URL),
),
);
/ /...}}};Copy the code
Set the request header and timeout
In most cases, the request header is basically fixed, and some special headers may be required, which is used as the base configuration. When a special request header is needed, it is passed in as a parameter, overwriting the underlying configuration. New http.js file:
import axios from 'axios';
import qs from 'qs';
const requestList = [];// Request list
const CancelToken = axios.CancelToken; // Cancel the list
const sources = {}; / / save the request
axios.defaults.timeout = 10000;
axios.defaults.headers.get['Content-Type'] = ContentType.FORM;
axios.defaults.headers.post['Content-Type'] = ContentType.JSON;
axios.defaults.baseURL = process.env.BASE_URL;
axios.defaults.withCredentials = true;
Copy the code
Encapsulating request method
The encapsulated method is introduced and reencapsulated into a method exposed on the interface to be called
// Configuration typeinterface ConfigType { loading? : boolean;// Whether to display loadingisPubParam? : boolean;// Whether to take public parametersContentType? : string; } enum ContentType {JSON = 'application/json; charset=utf-8',
FORM = 'application/x-www-form-urlencoded; charset=utf-8',}const request = function (url, params, config, method) {
return new Promise((resolve, reject) = > {
axios[method](url, params, Object.assign({}, config))
.then(
(response) = > {
resolve(response.data);
},
(err) = > {
if (err.Cancel) {
console.log(err);
} else {
reject(err);
}
},
)
.catch((err) = > {
reject(err);
});
});
};
export const post = (url, params, config: ConfigType = {}) = > {
if(config.isPubParam) params = { ... pubParams, ... params }; params = qs.stringify(params);return request(url, params, config, 'post');
};
export const get = (url, params, config: ConfigType = {}) = > {
if(config.isPubParam) params = { ... pubParams, ... params };return request(url, { params }, config, 'get');
};
Copy the code
Multi-domain case
// Set multiple domain names in different environments
const setBaseUrl = (options) = > {
let baseURL = ' ',
baseURL2 = ' ';
if (process.env.NODE_ENV === 'production') {
baseURL = process.env. ONLINE_URL;
baseURL2 = process.env.ONLINE_URL_2;
} else {
baseURL = process.env. TEST_URL;
baseURL2 = process.env. TEST_URL_2;
}
// Replace the corresponding interface domain name
if (/^\/api\//.test(options.url)) {
options.url = baseURL + options.url;
} else if (/^\/base\/test\//.test(options.url)) { options.url = baseURL2 + options.url; }};Copy the code
Request interceptor
Request interceptors can add tokens to each request, which can be easily maintained after unified processing
axios.interceptors.request.use(
(config) = > {
const request =
JSON.stringify(config.url) + JSON.stringify(config.data || ' ');
setBaseUrl(config); // Call the multi-domain case function
// Check whether token exists before request, handle single sign-on case
config.cancelToken = new CancelToken((cancel) = > {
sources[request] = cancel;
});
if (requestList.includes(request)) {
sources[request]('Cancel duplicate request');
} else {
requestList.push(request);
if (config['loading'])
// toast. show(' loading...... ')
}
return config;
},
function (error) {
return Promise.reject(error); });Copy the code
Response interceptor
The response interceptor can perform a layer of operations after receiving the response, such as judging login status and authorization according to the status code. If multiple domain interfaces exist, it can also perform interception processing here to update the BaseURL of the current interface.
axios.interceptors.response.use(
(response) = > {
const request =
JSON.stringify(response.config.url) +
JSON.stringify(response.config.data);
requestList.splice(
requestList.findIndex((item) = > item === request),
1,);if (requestList.length === 0) {
Toast.clear();
}
if (response.status === 200) {
switch (response.data.returncode) {
case -5:
Toast.show('Authentication failed, please log in again! ');
break;
case 102:
Toast.show('Operation too fast, please try again later! ');
break; }}else {
return Promise.reject(response)
}
return response;
},
(error) = > {
if (axios.isCancel(error)) {
requestList.length = 0;
Toast.clear();
throw new axios.Cancel('cancel request');
} else {
// Different return codes in failure cases are handled accordingly
switch (error.response.status) {
case 500:
Toast.show('Network request failed! ');break; }}return Promise.reject(error); });Copy the code
application
Put all interfaces into the index.js file in the API directory
import { get, post } from './http'
export const getUser = (params = {}) => get('/api/getuser', params)
Copy the code
Next call to the page
import * as API from 'api/index'
API.getUser({ id: 200 }).then(res= > {
console.log(res)
})
Copy the code
This does not put the API unified management, convenient maintenance and expansion after.
conclusion
- Encapsulation is one of the polymorphisms in programming languages, simple pair
axios
Encapsulation, you can realize the infinite charm it brings. - A good solution is to encapsulate it according to the needs of the project and make it easy to use.
reference
- Axois
- Parse the Axois source code