Make writing a habit together! This is the 8th day of my participation in the “Gold Digging Day New Plan · April More Text Challenge”. Click here for more details.

The introduction

Readers familiar with Vue will be familiar with Axios, but Axios alone is not enough for our daily use, so many times we need to re-wrap Axios to meet the needs of the project. Let’s talk about the encapsulation of AXIos in Vue.

How to encapsulate AXIOS in a Vue project

The axios file is encapsulated in the directory SRC /utils/ HTTPS. Ts, which exposes the callApi function

Determine the HTTP status code

It is very important to have a prompt that displays the real-time status of the interface. On the one hand, it is convenient for the front-end personnel to locate the cause of the problem, and it can also provide users with prompt guidance in some complicated special scenarios.

This encapsulates the common errorCode method to achieve decoupling and facilitate later maintenance and code reading.

Errorcode. ts: used to define the returned errorCode

Export default {'400': 'Request header error ', '401':' Authentication failed, system resources cannot be accessed, please log in again ', '403': 'current operation does not have permission ', '404':' Access resource does not exist ', '500': 'Server error, '503':' service unavailable ', 'default': 'System unknown error, please report to administrator'}Copy the code

Http. ts: Used for AXIOS encapsulation

import axios from 'axios' import errorCode from '@/utils/errorCode' import { ElMessage, ElMessageBox } from 'element-plus' axios.defaults.headers['Content-Type'] = 'application/json; Const service = axios.create({// the request in axios is configured with the baseURL option, indicating that the request is the public part of the URL baseURL: Process.env.vue_app_base_api, // timeout: 10000}) / / request interceptor service. The interceptors. Request. Use (config = > {the if (getToken () &&! IsToken) {config. Headers [' Authorization '] = 'Bearer' + getToken () / / make each request with a custom token please according to the actual situation to modify} return config}, Error = > {the console. The log (error) Promise. Reject (error)}) / / response blocker service. Interceptors. Response. Use (res = > {/ / Successful status code is not set the default state of const code = res. Data. The code | | 200; / / for errors information const MSG = res. Data. MSG | | errorCode [code] | | errorCode [' default '] / / binary data is returned directly if (res) request) responseType = = = "blob" | | res. Request. ResponseType = = = 'arraybuffer') {return res. Data} / / judgment status code if (code = = = 200) {return res. The data }else if(code === 401){return promise. reject(MSG)}else{ElMessage({message: MSG, type: 'error' }) return Promise.reject(msg) } }, error => { let { message } = error; If (message == "Network Error") {message = "Network Error"; } else if (message.includes("timeout")) {message = "system interface request timed out"; } else if (message.includes("Request failed with status code")) {message = "system interface" + message.substr(message.length-3) + "exception "; } ElMessage({ message: message, type: 'error', duration: 5 * 1000 }) return Promise.reject(error) } ) export default serviceCopy the code

Prevent repeated Loading requests

Asynchronous data request is a very common scenario in projects. A good Loading effect can greatly enhance user experience. If a Loading layer appears immediately after a request is initiated, users will not be able to click again, resulting in repeated requests.

The most common way to use Loading in a project is to enable Loading before a request is initiated and to disable Loading after a request is responded in order to prevent repeated requests. However, the following phenomena often occur in actual development:

  • Loading is enabled before a request is initiated. However, after the request is successfully invoked, the page is in Loading state.
  • If you forget to enable Loading before sending a request, you may click the Loading button repeatedly, which affects user experience.

Therefore, in order to avoid the above problems, it is decided to encapsulate Loading in Axios to achieve the purpose.

Then how to encapsulate Loading requires us to consider the following things:

  • To initiate multiple requests at the same time, we only need to display one Loading layer, and do not need to generate multiple layers to cause repeated display.
  • Loading layers that make multiple requests at the same time are displayed and destroy is turned off in response to the last request.
  • This feature is still configurable.

The Loading effect of ElementPlus is used as an example.

The common method of loading is encapsulated here to achieve decoupling and facilitate later maintenance and code reading.

Load. ts: used to define interface loading,

/** * Global loading effect: Merge multiple loading requests to avoid repeating loading requests * When showLoading is called once, the number of times is +1; Loading * When closeLoading is called once, loading * is -1. Loading */ import {ElLoading} from 'element-plus'; Let loadingRequestCount = 0; // Initialize loading let loadingInstance; ++ export showLoading = (target) => {if (loadingRequestCount === 0) {loadingInstance = Elload. service({lock: true, text: 'loading... ', BACKGROUND: 'rgba(0, 0, 0, 0.7)'}); } loadingRequestCount++} // write a function to hide loading, -- export closeLoading = () => {if (loadingRequestCount <= 0) return loadingRequestCount-- if (loadingRequestCount === 0) { loadingInstance.close(); }}Copy the code

Http. ts: Used for AXIOS encapsulation

import axios from 'axios' import { showLoading, closeLoading } from "@/utils/loading"; axios.defaults.headers['Content-Type'] = 'application/json; Const service = axios.create({// the request in axios is configured with the baseURL option, indicating that the request is the public part of the URL baseURL: Process.env.vue_app_base_api, // timeout: 10000}) / / open loading showLoading () / / request interceptor service. The interceptors. Request. Use (config = > {the if (getToken () &&! IsToken) {config. Headers [' Authorization '] = 'Bearer' + getToken () / / make each request with a custom token please according to the actual situation to modify} return config}, Error = > {the console. The log (error) Promise. Reject (error)}) / / response blocker service. Interceptors. Response. Use (res = > {/ / closed loading, The delay processing adopted here is to combine loading request effect. SetTimeout (() => {closeLoading()}, 200)}, error => {setTimeout(() => {closeLoading()}, 200) return Promise.reject(error) } ) export default serviceCopy the code

If the request fails, retry automatically

In real projects, requests often fail because the network is unreliable. To solve this problem, the usual practice is to add a retry mechanism. After a request fails, it automatically re-initiates multiple requests until the set number of times is reached. In this way, the success of the request can be guaranteed as much as possible and the service stability can be improved.

Common.ts: public functions

Export let isJsonStr = STR => {if (typeof STR == 'string') {try {var obj = json.parse (STR); if (typeof STR == 'string') {var obj = json.parse (STR); if (typeof obj == 'object' && obj) { return true; } else { return false; }} Catch (e) {console.log('error: '+ STR + '!!! ' + e); return false; }}};Copy the code

AgainRequest. Ts: Used to define retry requests

import { isJsonStr } from './common'; export function againRequest(err, axios) { let config = err.config; // config.retry Retry times configured on an interface. If (! config || ! config.retry) return Promise.reject(err); / / set config variables used to record a retry count default to 0. __retryCount = config. __retryCount | | 0; If (config.__retryCount >= config.retry) {return promise.reject (err); } // Number of retries config.__retrycount += 1; Var backoff = new Promise(function(resolve) {setTimeout(function() {resolve(); }, config.retryDelay || 1000); }); Return backoff.then(function() {// check whether it is JSON string // TODO: Parse (config.data) if (config.data && isJsonStr(config.data)) {config.data = json.parse (config.data); } return axios(config); }); }Copy the code

Http. ts: Used for AXIOS encapsulation

import axios from 'axios' import { againRequest } from '@/utils/requestAgainSend'; axios.defaults.headers['Content-Type'] = 'application/json; Const service = axios.create({// the request in axios is configured with the baseURL option, indicating that the request is the public part of the URL baseURL: Process.env.vue_app_base_api, // timeout: 10000}) / / request interceptor service. The interceptors. Request. Use (config = > {return config}, Error = > {Promise. Reject (error)}) / / response blocker service. Interceptors. Response. Use (res = > {return res. Data}, Error => {// Special handling is required for request cancellation if (! Axios.iscancel (error)) {return againRequest(error, Axios); } } ) export default serviceCopy the code

conclusion

There is no absolute standard for AXIos packaging, and the specific packaging results need to be appropriately changed according to the needs of the project. I hope the above packaging cases can give you some help.

conclusion

This article is the author’s personal study notes, if there are fallacies, please inform, thank you! If this article has been helpful to you, please click the “like” button. Your support is my motivation to keep updating.