preface
The controller code has just been pruned out of the project and there may be some errors or bloatcode
An identifier is required to intrude into the request header to mark the current request (optional)
Controller Introduction
- ⚠️ Can automatically close the non-routed page request after enabling the jump route (code is too intrusive, temporarily not open, can be designed by oneself)
- ✅ Enables the global loading box
- ✅ Enables disabling repeated requests
- ✅ Enables or disables repeated requests
- ✅ By default, requests with different parameters are not identified as the same request
- 😞 When a large amount of data is used, only defined parameters are used as the basis for repeated requests
The body of the
dependency
- axios
- qs
- Loading (elementui is self-substitutable)
1. Create controller files
Create a js file in the folder that wraps AXIos. Let’s name it axioshandler.js
Importing dependencies
import axios from "axios"
import qs from "qs"
import { Loading } from "element-ui"
Copy the code
Declare the variables required by the controller
export const MyKey = "my-cancel-close:" // Close the message header to distinguish error messages within a catch
let httpSequences = 0 // Record the request sequence
const pending = new Map(a)// Store request data
// customParams requests custom parameters and description
const CUSTOM_PARAMS = {
closeOtherPage: false.// {Boolean} Turn off non-routed page requests automatically,TODO:There are limitations, not open
bodyLoading: false./ / {Boolean | | String} open global load box
repeat: false.// {Boolean} Duplicate requests are not allowed. Requests with different parameters will not be closed
closeRepeat: false.// {Boolean} Enable Disables repeated requests. Requests with different parameters will not be closed
repeatParams: false.// {Boolean} If this parameter is enabled, requests with different parameters are identified as the same request. If this parameter is enabled, repeat or closeRepeat must be enabled
keys: [] // {Array
} This parameter is used when there is a large amount of data
}
Copy the code
2. Control methods
✅ Check whether the same request exists
/** * @param {String} requestUrl; */ export const findPending = (requestUrl) => {const findAll = [] for (const pendingObj of pending.values()) {if (pendingObj.requestUrl === requestUrl) { findAll.push(pendingObj) } } return findAll }Copy the code
✅ Closes a single request
/ * * * @ title close request * @ param {Object | | key} pendingObj request configuration or request sequences * / const delPending = (pendingObj) = > {if (typeof pendingObj == "string" || typeof pendingObj == "number") { const obj = pending.get(pendingObj) obj.cancel(`${MyKey}del`) pending.delete(pendingObj) } else { pendingObj.cancel(`${MyKey}del`) pending.delete(pendingObj.httpSequences) } }Copy the code
✅ closes requests for the same address
/** * @title * @param {String} requestUrl; */ export const delSamePending = (requestUrl) => {findPending(requestUrl). ForEach (pendingObj => { pendingObj.cancel(`${MyKey}delSame`) pending.delete(pendingObj.httpSequences) }) }Copy the code
✅ Close all requests (support receiving fuzzy address matching off)
*/ export const deleteAllRequest = (match = undefined) => {if (match) { for (const pendingObj of pending.values()) { if (pendingObj.requestUrl.toLowerCase().includes(match.toLowerCase())) { pendingObj.cancel() pending.delete(pendingObj.httpSequences) } } } else { for (const pendingObj of pending.values()) { pendingObj.cancel() } pending.clear() } }Copy the code
✅ serialize request parameters
/** * @title Serialized request parameters * @param {Object} config Request Object * @param {Array} keys Custom request parameter field * @return {String} request link + request parameter */ export const parseUrl = (config, keys = []) => { const objToStr = (obj = {}) => { if (typeof obj === "string") { obj = JSON.parse(obj) } const newobj = {} keys.forEach(key => { newobj[key] = obj[key] }) return qs.stringify(newobj) } let params if (Array.isArray(keys) && Keys.length) {if (config.method === "get" && config.params) {params = objToStr(config.params) } else if (config.method === "post" && config.data) { params = objToStr(config.data) } } if (! Params) {if (config.method === "post") {params = objToStr(config.data)} else {// All non-POST requests use params = objToStr(config.params) } } let configUrl = config.url configUrl += configUrl.includes("?" )? `&${params}` : `? ${params}` return configUrl }Copy the code
Three, the pre-processing before initiating the request
/** * @title * @param {Object} config config configuration */ export const interceptorsRequest = (config = {}) => { const pendingObj = {} const customParams = { ... CUSTOM_PARAMS, ... config? . CustomParams | | {}} pendingObj. CustomParams = customParams / / clean up configuration parameters the if (config. CustomParams) {config. CustomParams = Delete config.customParams} undefined // Insert a key into the request header for sequence identification
Return new Promise((resolve, reject) => {// Convert the request link to the format we want const configUrl = parseUrl(config, CustomParams. Keys) let requestUrl if (customParams repeatParams) {/ / different parameters are considered to be the same request, RequestUrl = configurl.split ("?") )[0] + "&" + config.method + "&myRepeatParams" } else { requestUrl = configUrl + "&" + config.method if (customParams.repeat) { requestUrl = requestUrl + "&myRepeat" } else if (customParams.closeRepeat) { requestUrl = requestUrl + "&myCloseRepeat" } }
If (customParams.repeat) {if (findPending(requestUrl).length) {return reject(new) Error(' ${MyKey}no-repeat '))}} else if (customParams.closerepeat) { CancelToken = new axios. cancelToken (cancel => {pendingobj.requestURL = RequestUrl Pendingobj.cancel = cancel}) // If (CustomParams.bodyLoading && Loading) {pendingobj.bodyLoading = Loading.service({ lock: true, body: true, customClass: "my-loading-body", text: CustomParams. BodyLoading | | "data load..." , spinner: "el-icon-loading", background: "rgba(0, 0, 0, 2)"})} config.headers.MyPending = httpSequences pending. HttpSequences pending. pendingObj) httpSequences = httpSequences + 1 resolve()Copy the code
Copy the code
})}
Iv. Handling of the request after completion
@param {Object} config config configuration of axios */ export const interceptorsResponse = (config = {}) => { const pendingObj = pending.get(config.headers? .mypending) if (pendingObj) {// If (pendingobj.myloadingBody) {pendingobj.myloadingBody? .close() } delPending(config.headers? .MyPending) } }Copy the code
5. Formal access project
The preparation work is complete, now we plug into the project code, and use the method is very simple
Open the JS file that wraps AXIOS, such as requist.js in the sample project
// Import processing methods
import { interceptorsRequest, interceptorsResponse, MyKey } from "./axiosHandler"
// Request interceptor
service.interceptors.request.use(async(config) => {
// HACK:Intercept registered
await interceptorsRequest(config)
/ /... other code
return config
}, error= > {
return Promise.reject(error)
})
// Response interceptor
service.interceptors.response.use(res= > {
// HACK:Response interception delete
interceptorsResponse(res.config)
},
error= > {
let { message } = error;
if (message.includes("etwork")) {
message = "System port connection is abnormal";
} else if (message.includes("timeout")) {
message = "System interface request timed out";
} else if (message.includes("failed")) {
message = "System port is abnormal";
}
// HACK:Whether to close the throw for repeated requests
if(! message.startsWith(MyKey)) { Message({message: message,
type: "error".duration: 5 * 1000})}return Promise.reject(error)
})
Copy the code
Six, use examples
Get, Post and other request methods, use the same method, only with customParams
🐛 cannot be re-initiated until the request is completed
return request({
url: "/login".method: "post",
data,
customParams: {
repeat: true}})Copy the code
🐛 Make a new request close the historical request (it will not be closed if the parameters are inconsistent)
return request({
url: "/login".method: "post",
data,
customParams: {
closeRepeat: true}})Copy the code
🐛 If the parameters are inconsistent each time, a new request is sent to close the historical request
return request({
url: "/login".method: "post",
data,
customParams: {
closeRepeat: true.repeatParams: true}})Copy the code
🐛 Used when there is a large amount of data. Initiate new requests and close historical requests
return request({
url: "/login".method: "post",
data,
customParams: {
closeRepeat: true.keys: ["uuid"]}})Copy the code
Source 📑
/ * * *@title Axios repeatedly requests control *@author Azil
* @version 0.0.1
* @time The 2021-11-20 * /
import axios from "axios";
import qs from "qs";
import { Loading } from "element-ui";
// The controller turns off the request information key to distinguish error messages within the catch
export const MyKey = "my-cancel-close:";
let httpSequences = 0; // Record the request sequence
const pending = new Map(a);// Store request data
// customParams requests custom parameters and description
const CUSTOM_PARAMS = {
closeOtherPage: false.// {Boolean} Automatically closes non-routed page requests after redirect is enabled,TODO:There are limitations, not open
bodyLoading: false./ / {Boolean | | String} open global load box
repeat: false.// {Boolean} Duplicate requests are not allowed. Requests with different parameters will not be closed
closeRepeat: false.// {Boolean} Enable Disables repeated requests. Requests with different parameters will not be closed
repeatParams: false.// {Boolean} If this parameter is enabled, requests with different parameters are identified as the same request. If this parameter is enabled, repeat or closeRepeat must be enabled
keys: [].// {Array
} When a large amount of data is used, only parameters from the definition are used as criteria for repeated requests
};
/ * * *@title Query whether the same request * exists@param {String} RequestUrl specifies the requestUrl with the parameter *@return {Array} The path with the same request parameters */ is displayed
export const findPending = (requestUrl) = > {
const findAll = [];
for (const pendingObj of pending.values()) {
if(pendingObj.requestUrl === requestUrl) { findAll.push(pendingObj); }}return findAll;
};
/ * * *@title Close the request@param {Object || key} PendingObj requests configuration or request sequence */
const delPending = (pendingObj) = > {
if (typeof pendingObj == "string" || typeof pendingObj == "number") {
const obj = pending.get(pendingObj);
obj.cancel(`${MyKey}del`);
pending.delete(pendingObj);
} else {
pendingObj.cancel(`${MyKey}del`); pending.delete(pendingObj.httpSequences); }};/ * * *@title Close requests * for the same address@param {String} RequestUrl Specifies the link to the request with the parameter */
export const delSamePending = (requestUrl) = > {
findPending(requestUrl).forEach((pendingObj) = > {
pendingObj.cancel(`${MyKey}delSame`);
pending.delete(pendingObj.httpSequences);
});
};
/ * * *@title Clear all requests *@param {String} Match Fuzzy match deleted */
export const deleteAllRequest = (match = undefined) = > {
if (match) {
for (const pendingObj of pending.values()) {
if(pendingObj.requestUrl.toLowerCase().includes(match.toLowerCase())) { pendingObj.cancel(); pending.delete(pendingObj.httpSequences); }}}else {
for (const pendingObj ofpending.values()) { pendingObj.cancel(); } pending.clear(); }};/ * * *@title Serialize request parameters *@param {Object} Config Request object *@param {Array} Keys Custom request parameter field *@return {String} Request link + request parameter */
export const parseUrl = (config, keys = []) = > {
const objToStr = (obj = {}) = > {
if (typeof obj === "string") {
obj = JSON.parse(obj);
}
const newobj = {};
keys.forEach((key) = > {
newobj[key] = obj[key];
});
return qs.stringify(newobj);
};
let params;
if (config.method === "post" || config.method === "put") {
params = objToStr(config.data);
} else {
params = objToStr(config.params);
}
let configUrl = config.url;
configUrl += configUrl.includes("?")?` &${params}` : `?${params}`;
return configUrl;
};
/ * * *@title Processing before the request is initiated *@param {Object} Config Axios config */
export const interceptorsRequest = (config = {}) = > {
const pendingObj = {};
constcustomParams = { ... CUSTOM_PARAMS, ... (config? .customParams || {}), }; pendingObj.customParams = customParams;// Clear the configuration parameters
if (config.customParams) {
config.customParams = undefined;
delete config.customParams;
}
return new Promise((resolve, reject) = > {
// Convert the request link to the format we want to process
const configUrl = parseUrl(config, customParams.keys);
let requestUrl;
if (customParams.repeatParams) {
// Different parameters are considered the same request, but repeat and closeRepeat do not affect each other
requestUrl = configUrl.split("?") [0] + "&" + config.method + "&myRepeatParams";
} else {
requestUrl = configUrl + "&" + config.method;
if (customParams.repeat) {
requestUrl = requestUrl + "&myRepeat";
} else if (customParams.closeRepeat) {
requestUrl = requestUrl + "&myCloseRepeat"; }}if (customParams.repeat) {
// Repeat requests are not allowed
if (findPending(requestUrl).length) {
return reject(new Error(`${MyKey}no-repeat`)); }}else if (customParams.closeRepeat) {
// Allow repeated requests to be made, but turn off historical repeated requests and keep only the latest one
delSamePending(requestUrl);
}
config.cancelToken = new axios.CancelToken((cancel) = > {
pendingObj.requestUrl = requestUrl;
pendingObj.cancel = cancel;
});
// Whether to open the full-screen mask
if (customParams.bodyLoading && Loading) {
pendingObj.bodyLoading = Loading.service({
lock: true.body: true.customClass: "my-loading-body".text: customParams.bodyLoading || "Data loading...".spinner: "el-icon-loading".background: "Rgba (0, 0, 0, 0.5)"}); }// TODO:A key needs to be inserted into the request header for sequence identification
config.headers.MyPending = httpSequences;
pendingObj.httpSequences = httpSequences;
pending.set(httpSequences, pendingObj);
httpSequences = httpSequences + 1;
resolve();
});
};
/ * * *@title Post-request processing *@param {Object} Config Axios config */
export const interceptorsResponse = (config = {}) = > {
constpendingObj = pending.get(config.headers? .MyPending);if (pendingObj) {
// Disable loading if there is loading
if(pendingObj.myLoadingBody) { pendingObj.myLoadingBody? .close(); } delPending(config.headers? .MyPending); }};/ * * *@title Request exception handling */
export const errorHandler = (error) = > {
console.error(/ Request exception handling /, error);
for (const pendingObj of pending.values()) {
// Disable loading if there is loading
if(pendingObj.myLoadingBody) { pendingObj.myLoadingBody? .close(); }}};Copy the code