“This is the third day of my participation in the November Gwen Challenge. See details of the event: The last Gwen Challenge 2021”.
preface
To begin with, this article will share the ideas and methods of encapsulating HTTP requests that I often use in my work. Since the most commonly used framework in my work is Vue, naturally, this article is based on AXIos
Why encapsulate AXIos
One student might ask, “Why bother wrapping the axios one more time when it’s already great and has everything you need?”
To those who do, I can only say, “Good question. After reading the article, don’t ask again.”
Consider the following questions:
- What would you do if you had to set the request header uniformly
- What would you do if you wanted to intercept the return value and process the data for a particular interface
- What would you do if you had to set up loading animations
It is not difficult to see that the above problems have one thing in common, that is, unified treatment, which is why the need for encapsulation
How to encapsulate
Project directory structure
First we create a service folder in the project directory for the request class. Then we create an HTTP folder in the project folder for the constructor, interceptor, request exit, and aiP1 folder for the specific request. It can also be divided by page structure or component structure, depending on the actual project.)
Detailed interpretation of the
The interceptor
The interceptors. Js file is used to store interceptors. What does the interceptor do
In interceptors, you can do unified handling for request methods, request parameters, interface callback parameters, request exceptions, response exceptions, and so on
Going back to the three questions at the beginning of this article, questions 2 and 3 can be handled inside the interceptor
// service/http/interceptors.js
// HTTP request interceptor
const request = config= > {
Config is the axiOS request configuration item
if (config.method === 'get') {
// do something
}
if (config.method === 'post') {
// do something
}
return config;
};
const requestError = err= > {
const { config, code, message } = err;
// Here you can do some abnormal monitoring such as error interface, error information collection for online service troubleshooting
// do something
// Since AXIos returns a PROMISE entity, in error interception, null data is returned to ensure that the interface responds without exception
return Promise.reject({ code, data: {}}); };// HTTP response interceptor
// Response interceptors are used to cache interfaces in conjunction with caching policies
const response = res= > {
const { config, data } = res;
// do something
return res.data;
};
const responseError = err= > {
const { config, code, message } = err;
// Here you can do some abnormal monitoring such as error interface, error information collection for online service troubleshooting
// do something
// It is also possible to call the cache data on the wrong interface in conjunction with the business cache policy to ensure the normal service
// do something
// Whether you need to call the cache data to return different entities for different interfaces
// return data (data from cache)
return Promise.reject({ code, data: {}}); };export default {
request,
requestError,
response,
responseError
};
Copy the code
The common use of interceptor production has been mentioned in the code block and above, and more uses can be used to expand the combined business (definitely can play very ridiculous).
The constructor
Constructors, as the name implies, are classes that construct request instances
In the constructor, we can set the interface domain name needed for our business and pass the interceptor instance into the AXIOS instance method
It is worth noting that while we can also do business with the request method in the constructor, in order to maintain the principle of one thing doing one thing, we should just let it construct axios instances separately in the constructor
// service/http/fetch.js
import axios from 'axios';
import intercepors from './interceptors';
// Create different AXIos entities
let fetch1 = createFetchByHost('//host1.cn'.true);
let fetch2 = createFetchByHost('//host2.cn'.false);
// The AXIos entity constructor can be modified according to business requirements
/** * Create fetch *@param {string} url* /
function createFetchByHost(url, withCredentials = false) {
let http = axios.create({
baseURL: process.env.NODE_ENV === 'production' ? url : ' '.timeout: 5000.withCredentials: withCredentials,
headers: { post: { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'}}});// Configure the common part of the request header
http.interceptors.request.use(intercepors.request, intercepors.requestError);
http.interceptors.response.use(intercepors.response, intercepors.responseError);
return http;
}
export default { fetch1, fetch2 };
export { fetch1, fetch2 };
Copy the code
Request the export
There’s nothing to be said for the request exit, which simply exposes the axios instance constructed by the constructor and pastes the sample code directly. Right
// service/http/index.js
import { fetch1, fetch2 } from './fetch';
class Api {
constructor() {
this.fetch1 = fetch1;
this.fetch2 = fetch2; }}export default Api;
export { Api };
Copy the code
Service interface encapsulation
We’ve covered interceptors, constructors, request exits, and basically we have a semi-finished product coming up. Now we can encapsulate the specific business interface based on the semi-finished product and we’re done
In the constructor, we construct different axios instances for different domains, and here we will apply these instances to construct specific interface classes. In this way, we can unify processing for a particular interface
Question 3 at the beginning of the article can be dealt with here. In addition, we can also combine interceptor, the specified domain name to do interface cache
// service/api1/index.js
import Api from '.. /http';
class Api1 extends Api {
async apiA({ params = ' ' }) {
return this.fetch1.post('/api/path', { params }).catch(() = > ({ result: 'error'.data: {}})); }}export default new Api1();
Copy the code
The service class export
This is also the final step in the encapsulation. After we complete the steps above, expose the Service class for business use
// service/index.js
import { fetch } from './http';
import api1 from './api1';
const install = VUE= > {
VUE.prototype.$http = fetch;
VUE.prototype.$httpApi1 = api1;
};
export default { api1, install };
export { api1 as api1Service, install };
Copy the code
When we expose the Service class, we assign the AXIos instance and the business interface instance to the VUE stereotype attribute. This is adjusted according to the business. My personal preference is to do this because it is more convenient…
How to apply
How to apply this thing, so I don’t have to spend too much ink, just post an example
Call / * * * * * * * * * * /
// In the component that references the vue instance
// this.$httpApi1.apiA()
// In pure JS methods
// import { api1Service } from '@/service';
// api1Service.apiA()
Copy the code