Packaging ideas
Index. ts We need to create an axios folder in the SRC root directory and create an index.ts file that encapsulates the AXIos configuration (instantiated request configuration, request interceptor, corresponding interceptor) and corresponding methods (login jump, message prompt, error handling, etc.).
Base.ts this file is mainly used in the case of project extension, different modules need to call different interfaces (the base address of the request baseURL) and the preparation in the early stage is convenient for the later maintenance
Request. ts encapsulates axios-based configuration methods such as GET, POST, PUT, and delete.
Api. ts introduces this module in main.ts, including all interface data information written to this file.
index.ts
The package is as follows. Considering the single responsibility, the index block encapsulates only AXIos
// index.ts
import axios, { AxiosRequestConfig, Method } from "axios";
import router from "@/router";
import store from "@/store";
import { message } from 'ant-design-vue'
import { storage } from ".. /storage/storage";
import { dataList } from "@/components/aspin/data";
/** * redirects to the login page */ Carries a route to the current page in order to return to the current page after the login page is complete
const toLogin = () = > {
router.replace({
name: 'LoginPage'}); }/** * Request failed error unified processing *@param {Number} Status Indicates the status code of the failed request */
const errorHandle = (status: number, other: string) = > {
// Determine the status code
switch (status) {
case 302: message.error('Interface redirected! ');
break;
case 400:
message.error("Error in request sent, server did not create or modify data ==>" + status)
break;
// 401: Not logged in
// If you do not log in, the login page is displayed and the path of the current page is displayed
// Return to the current page after successful login. This step must be performed on the login page.
case 401: / / redirection
message.error("Token: Login invalid ==>" + status + ":" + store.state.Roles)
storage.remove(store.state.Roles)
storage.get(store.state.Roles)
router.replace({
path: '/Login'});break;
// 403 Token expired
// Clear the token and jump to the login page
case 403:
message.error("Login expired, user is authorized, but access is prohibited ==>" + status)
// store.commit('token', null);
setTimeout(() = > {
router.replace({
path: '/Login'}); },1000);
break;
case 404:
message.error("Network request does not exist ==>" + status)
break;
case 406:
message.error("Requested format not available ==>" + status)
break;
case 408: message.error("Request timed out!")
break;
case 410:
message.error("Requested resource permanently deleted and no longer available ==>" + status)
break;
case 422:
message.error("A validation error occurred while creating an object ==>" + status)
break;
case 500:
message.error("Server error, please check server ==>" + status)
break;
case 502:
message.error("Gateway error ==>" + status)
break;
case 503:
message.error("Service unavailable, server temporarily overloaded or maintenance ==>" + status)
break;
case 504:
message.error("Gateway timeout ==>" + status)
break;
default:
message.error("Other errors error ==>" + status)
}
}
// Define the interfaceinterface PendingType { url? : string; method? : Method; params: any; data: any; cancel: any; }// Cancel duplicate requests
const pending: Array<PendingType> = [];
const CancelToken = axios.CancelToken;
// Remove duplicate requests
const removePending = (config: AxiosRequestConfig) = > {
for (const key in pending) {
const item: number = +key;
const list: PendingType = pending[key];
// Execute the function body when the current request exists in the array
if (list.url === config.url && list.method === config.method && JSON.stringify(list.params) === JSON.stringify(config.params) && JSON.stringify(list.data) === JSON.stringify(config.data)) {
// Perform the cancel operation
list.cancel('Operation too frequent, please try again later');
// Remove the record from the array
pending.splice(item, 1); }}};/* Instantiate the request configuration */
const instance = axios.create({
headers: {
// the PHP post request header must have this or it will not receive the value
"Content-Type": "application/json; charset=UTF-8"."Access-Control-Allow-Origin-Type": The '*'
},
// Request duration
timeout: 1000 * 30.// The requested base addressTODO:This will change the API for different modules later
baseURL: process.env.VUE_APP_API_URL,
/ /? "Test"
// : "official ",
// Indicates whether credentials are required for cross-domain requests
withCredentials: false,})/** * Request interceptor * Each request is preceded by a token */ in the request header if it exists
instance.interceptors.request.use(
config= > {
removePending(config);
config.cancelToken = new CancelToken((c) = > {
pending.push({ url: config.url, method: config.method, params: config.params, data: config.data, cancel: c });
});
// During login process control, users can be judged based on whether tokens exist locally
// But even if the token exists, it is possible that the token is expired, so the token is carried in the request header each time
// The background determines the login status of the user according to the token carried and returns the corresponding status code to us
// Then we can do some uniform operations based on the status code in the response interceptor.
// const token = store.state.token;
// localStorage.setItem('token', token);
if (storage.get(store.state.Roles)) {
store.state.Roles
config.headers.Authorization = storage.get(store.state.Roles);
}
return config;
},
error= > {
message.error(error.data.error.message);
return Promise.reject(error.data.error.message); })// Response interceptor
instance.interceptors.response.use(function (config) {
dataList.show = true
removePending(config.config);
// The request succeeded
if (config.status === 200 || config.status === 204) {
setTimeout(() = > {
dataList.show = false
}, 400)
return Promise.resolve(config);
} else {
return Promise.reject(config);
}
// The request failed
}, function (error) {
const { response } = error;
if (response) {
errorHandle(response.status, response.data.message);
// Retry the timeout request
const config = error.config;
// The number of global requests, the gap between requests
const [RETRY_COUNT, RETRY_DELAY] = [3.1000];
if (config && RETRY_COUNT) {
// Sets the variable used to track retry counts
config.__retryCount = config.__retryCount || 0;
// Check whether the total number of retries has been used up
if (config.__retryCount >= RETRY_COUNT) {
return Promise.reject(response || { message: error.message });
}
// Increase the retry count
config.__retryCount++;
// Create new Promises to handle exponential fallbacks
const backoff = new Promise<void> ((resolve) = > {
setTimeout(() = > {
resolve();
}, RETRY_DELAY || 1);
});
// Instance retry the request Promise
return backoff.then(() = > {
return instance(config);
});
}
return Promise.reject(response);
} else {
// Handle network outages
// If the request times out or the network is disconnected, update the network status of state
// The network state controls the display and hiding of a global disconnection alert component in app.vue
// Add some operations in the case of disconnection
store.commit('networkState'.false); }})// Just consider a single responsibility, which encapsulates only AXIos
export default instance
Copy the code
base.ts
The baseUrl of each module is differentiated to facilitate later maintenance and management
// base.ts
export class Base {
/* Public module */
static env = process.env.NODE_ENV === "development"
? "http://localhost:8087"
: "Https://produceCommon.com (production line address)"
}
Copy the code
You can also set it directly in index.ts so that you don’t need base.ts
const instance = axios.create({
// The requested base addressTODO:This will change the API for different modules later
baseURL: process.env.VUE_APP_API_URL,
})
Copy the code
The root directory needs to be configured
.env.development
NODE_ENV = 'development'
# VUE_APP_API_URL = 'https://localhost:5001/'
VUE_APP_API_URL = 'http://localhost:8087/'
Copy the code
.env.production
NODE_ENV = 'production' VUE_APP_API_URL = 'http://129.xxxxx/'Copy the code
request.ts
Wrap axios’ GET and POST methods, and the rest of the interface calls can also be written to this file for easy management.
// request.ts
import axios from "./index";
import qs from "qs";
export class Request {
/** * get method *@param {string} The url path *@param {object} Params parameters * /
static get = (url: string, params? : any) = > {
return new Promise((resolve, reject) = > {
axios.get(url, { params: params }).then(res= > {
resolve(res);
}).catch(err= >{ reject(err); })})}static post = (url: string, params? : any) = > {
return new Promise((resolve, reject) = > {
axios.post(url, qs.stringify(params)).then(res= > {
resolve(res);
}).catch(err= >{ reject(err); }}})})Copy the code
api.ts
Vue page to use the API interface
// The purpose of using install is for ts in main.ts
// Can't be called directly through vue.prototype. $Api
// The global method will talk about mounting using plug-ins.
// api.ts
import { Base } from "./base";
import { Request } from "./request";
class api {
/* API interface module */
public static article = {
// Set directly in index.ts without the Base module
genre: () = > Request.get('/api/SnArticle/GetCountAsync'),
// Encapsulate the call based on the Base module
genres: () = > Request.get(`${Base.env}/api/SnArticle/GetCountAsync`),}}export {
api
}
Copy the code
index.vue
import { api } from '.. /.. /utils/api/api'
import { onMounted } from 'vue'
onMounted(async() = > {await QueryAll()
api.article.genre().then((res: any) = > {
console.log('genre' + res.data)
})
api.article.genres().then((res: any) = > {
console.log('genres' + res.data)
})
})
Copy the code
reference
Blog.csdn.net/qq_40031303…