question
In progressaxios
When encapsulating, I encountered a problem, that is, every time axios initiates a request, it will perform two response interceptions. I am very puzzled and can't figure it out for a while.
The code is as follows:
class Http { constructor(config) { = axios; = undefined; // Public header let defaultHeaders = { 'Content-Type': 'application/json;charset=UTF-8', 'Accept': 'application/json', // Specify through header, the retrieved data type is JSON 'application/json, text/plain, */*', 'x-end-point': '.10.' } if(config?.headers){ for (let i in ) { defaultHeaders[i] = [i]; } } axios({ // `baseURL` will be automatically added before `url` unless `url` is an absolute URL. // It can facilitate the passing of relative URLs to the axios instance method by setting a `baseURL` baseURL: config?.baseURL, // `url` is the server URL used for request url: config?.url, // `method` is the method used when creating a request method: config?.method || 'get', // `headers` is a custom request header to be sent soon headers: {...defaultHeaders}, // `params` is the URL parameter to be sent with the request // Must be a plain object or URLSearchParams object params: config?.method === 'get' ? config?.params || {} : {}, // `paramsSerializer` is a function responsible for `params` serialization // (. /package/qs, //) paramsSerializer: function(params) { return (params, {arrayFormat: 'brackets'}) }, // `data` is data sent as the requesting body // Applicable only to these request methods 'PUT', 'POST', and 'PATCH' // When `transformRequest` is not set, it must be one of the following types: // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams // - Browser exclusive: FormData, File, Blob // - Node exclusive: Stream data: config?.method === 'post' ? config?.params || {} : {}, // `timeout` specifies the number of milliseconds for the request timeout (0 means no timeout) // If the request charge exceeds the timeout, the request will be interrupted timeout: 0, // `withCredentials` indicates whether credentials are required when requesting across domains withCredentials: false, // If default is true, cross-domain, cross-domain carrying cookies are generated // `responseType` represents the data type of the server response, which can be 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream' responseType: 'json', // default }); // Add a request interceptor ( (config) => { // What to do before sending a request return config; }, function (error) { // What to do about the request error return (error); }); // Add a response interceptor ((res) => { const { status, data } = res; // Handle error status prompts let message = '' if (status < 200 || status >= 300) { // Handle http errors and throw them into business code message = (status) if (typeof === 'string') { = {code:status, message } } else { = status = message } } return ; }, function (error) { // Do something to respond to errors return (error); }); } get(url,params={}){ // Create a request for the user with a given ID return new Promise((resolve, reject) => { (url,{ params }).then(response => { // 2. If successful, call resolve(value) resolve(response); }) .catch(error => { // 3. If it fails, do not call reject(reason), but prompt for exception information reject(error) // ('The request error occurred: ' + ).then(r => {}); }).finally(() => { }) }); } post(url,params={}){ return new Promise((resolve, reject) => { (url, params).then(response => { // 2. If successful, call resolve(value) resolve(response); }) .catch(error => { // 3. If it fails, do not call reject(reason), but prompt for exception information reject(error) // ('The request error occurred: ' + ).then(r => {}); }).finally(() => { }) }); } showResState (state) { let message = ''; // Here are only some common examples, and configure them according to your needs switch (state) { case 400: message = 'Request error(400)' break case 401: message = 'Unauthorized,Please log in again(401)' break case 403: message = 'access denied(403)' break case 404: message = 'Request error(404)' break case 500: message = 'Server Error(500)' break case 501: message = 'Service not implemented(501)' break case 502: message = 'Network error(502)' break case 503: message = 'Service not available(503)' break default: message = `There was an error in connection(${state})!` } return `${message},Please check the network or contact the website administrator!` } // The required configuration items will be passed in when the plug-in is initialized autoAddToken (config) { // Modify the config configuration item during the request phase to add token to it. The specific attribute name can be customized. ??= {} = || null return config } } export default Http;
Friends who have encountered this type of problem may see the problem at a glance, and friends who have never encountered this problem may suffer a little more.
reason
If you use use, just like the use in it, you will constantly add interceptors to the axios object. Since I put the interceptor in the function, as long as the function is executed, the interceptor function will be added to the axios object again.
So, the recommended way is to put the interceptor outside the function, but my needs determine that I must put it inside the function, so how to solve it?
solve
Add the unique variable identifier in the file let interceptor = null to make judgments. As long as the interceptor exists, it will not continue to be added. Some codes are as follows:
if (!) { // Add a response interceptor = ((res) => { const { status, data } = res; // Handle error status prompts let message = '' if (status < 200 || status >= 300) { // Handle http errors and throw them into business code message = (status) if (typeof === 'string') { = {code:status, message } } else { = status = message } } return ; }, function (error) { // Do something to respond to errors return (error); }); }
What's wrong. The interceptor must be extracted outside the class, and the problem must be solved.
Only some of the main codes are posted here:
import axios from "axios"; /* Place the interceptor outside the encapsulation class */ // Add a request interceptor( (config) => { // What to do before sending a request? Add token and other authentication functions //... return config; }, function (error) { // What to do about the request error return (error); }); // Add a response interceptor((res) => { const { status } = res; // What to do before sending the result? Handle the error status prompt //... return ; }, function (error) { // Do something to respond to errors return (error); }); class Http { constructor(config) { = axios; // The configuration still needs to be processed here, the code is omitted = config; } // Get request get(url,params={},headers={}){ // ... } // POST request post(url,params={},headers={}){ // ... } } export default Http; // If there is no special needs, just use this one object. The public header can be configured here. If multiple instances are needed, multiple instances can be created in this way for export.export const Axios = new Http({ headers: { 'x-http-token': 'xxx' } });
The specific method is not described here, but only a description of the problem is made. In the future, we will write a separate article and then explain it in detail.
The above is the detailed content of solving the problem of multiple executions of axios interceptors. For more information about multiple executions of axios interceptors, please pay attention to my other related articles!