Small knowledge, big challenge! This paper is participating in theEssentials for programmers”Creative activities.

👉 practice makes perfect, shortage in one, success depends on forethought. Tang Han Yu, “Into Learning Solutions”

preface

The axios wrapper helps simplify the code and facilitates later maintenance.

The installation

npm install axios; / / install axios
Copy the code

The introduction of

import axios from 'axios'
Copy the code

Interface root Address

const baseUrl = API_BASE_URL // Injected by webPack's DefinePlugin

webpackConfig
    .plugin('define')
        .use(require('webpack/lib/DefinePlugin'), [{
            // NODE_ENV environment variable, the development environment is: 'development', to ensure that the test environment package and production environment are the same, the test environment and production environment are 'production'.
            'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
            // The current application environment (dev: 'dev', test: 'test', production: 'prod')
            'process.env.APP_ENV': JSON.stringify(process.env.APP_ENV),
            // The background interface requests the address
            'API_BASE_URL': JSON.stringify(config.meshProp('apiBaseUrl')),
            // Home page path
            'APP_INDEX_PATH': JSON.stringify(indexPath),
            // Routing mode
            'APP_ROUTER_MODE': JSON.stringify(config.meshProp('routerMode')),
            // Whether to use the Element library
            'APP_USE_ELEMENT': JSON.stringify(config.meshProp('useElement')),}])Copy the code

Config. js: Configures some system names, API root paths, etc

const path = require('path')
const os = require('os')
const packageName = 'focm' // Project package name
const localIP = getLocalIP() // Local IP address

module.exports = {
    // Default configuration
    default: {
        // System name, used to set the title in the page head
        appName: 'xxxxx'.// Whether to apply multiple pages
        isMulti: false.// Whether mobile terminal is supported
        isMobile: false./ / whether or not to use Element component library (https://element.eleme.cn/#/zh-CN/)
        useElement: true./ / routing model (value of hash or history, reference: https://router.vuejs.org/)
        routerMode: 'hash'.// The interface requests the root path
        apiBaseUrl: ' '. },// Configuration of the development environment
    dev: {
        apiBaseUrl: '/api'.host: localIP,
        port: 8080.autoOpenBrowser: true.// Whether to open the browser automatically
        writeToDisk: false.// Whether to write the generated file to disk
        proxyTable: {
            '/api': {
                target: 'http://focm-web.focms.paas.test'.changeOrigin: true}}},// Test environment configuration
    test: {
        // The interface requests the root path
        apiBaseUrl: '/focm'.outputRoot: path.resolve(__dirname, 'dist/test'),
        publish: {
            remoteHost: 'x.x.x.x'.remotePort: '22'.remoteUsername: 'qinglianshizhe'.remotePassword: 'xxxxxx'.remoteAppRoot: `/xxx/xxx/${packageName}`.webUrl: 'http://xxxxx.com/'}},// Production environment configuration
    prod: {... }}// Obtain the local IP address
function getLocalIP () {
    let interfaces = os.networkInterfaces()
    for(let devName in interfaces){
        let iface = interfaces[devName]
        for(let i=0; i<iface.length; i++){let alias = iface[i];
            if(alias.family === 'IPv4'&& alias.address ! = ='127.0.0.1' && !alias.internal){
                returnalias.address; }}}return 'localhost'
}
Copy the code

Let’s go ahead and wrap Axios

/** * Service exception class */

class BusinessError extends Error {
    constructor (code, message, data) {
        super(message)
        this.code = code
        this.name = 'BusinessError'
        this.data = data
    }
}
/** * System exception class */
class SystemError extends Error {
    constructor (code, message, data) {
        super(message)
        this.code = code
        this.name = 'SystemError'
        this.data = data
    }
}
/ / axios configuration
axios.defaults.timeout = 10000
axios.defaults.headers.post['Content-Type'] = 'application/json; charset=UTF-8'

// Execute the POST request
function post (option, vm) {
    option.method = 'POST'
    return http(option, vm)
}

// Execute the GET request
function get (option, vm) {
    option.method = 'GET'
    return http(option, vm)
}

// Download the request
function download (option, vm) {
    option.method = option.method || 'GET'
    option.isDownload = true
    option.responseType = 'blob'
    return http(option, vm)
    }

/** * request background interface *@param Option parameter * URL: request path (will be concatenated to baseUrl, beginning with "/") * data: request parameter object * timeout: request timeout time (default: 10000, i.e. 10 seconds) * toastError: Automatically displays service exception information. The default value is true. When the value is false, the system does not automatically displays *@param Vm Vue object (used to automatically toast exception messages when exceptions occur) *@return {Promise} Promise object * /

function http (option, vm) {
    return new Promise((resolve, reject) = > {
        let method = option.method || 'POST'
        let url = baseUrl + option.url
        let timeout = option.timeout || 10000
        let headers = option.headers || {}
        let responseType = option.responseType
        let data = {} // You can set the default value here
        if (option.data) {
            if (option.data instanceof FormData) {
                headers['Content-Type'] = 'multipart/form-data'
                let formData = option.data
                Object.keys(data).forEach((key) = > {
                    formData.append(key, data[key])
                })
                data = formData
            } else{ data = { ... data, ... option.data } } }let requestOptions = { method, url, headers, timeout, responseType }
        if (method.toUpperCase() === 'GET') {
            requestOptions.params = data
        } else {
            requestOptions.data = data
        }
        axios(requestOptions).then( (res) = > {
            const contentDisposition = res.headers['content-disposition']
            // File download
            if (contentDisposition &&
        (/filename\*=UTF-8''(.*)/.test(contentDisposition) || /filename="(.*)"/.test(contentDisposition))) { // If the file is downloaded
                const utf8Match = contentDisposition.match(/filename\*=UTF-8''(.*)/) // Matches the utF-8 file name
                const normalMatch = contentDisposition.match(/filename="(.*)"/) // Matches a common English file name
                const filename = utf8Match ? decodeURIComponent(utf8Match[1]) : normalMatch[1]
                const blob = new Blob([res.data])
                const downloadElement = document.createElement('a')
                const href = window.URL.createObjectURL(blob)
                downloadElement.href = href
                downloadElement.download = filename
                document.body.appendChild(downloadElement)
                downloadElement.click()
                document.body.removeChild(downloadElement)
                window.URL.revokeObjectURL(href)
                resolve(res)
            } else { / / JSON information
                getResponseInfo(res).then((resInfo) = > {
                    responseInfoHandle(resInfo, resolve, reject, option, vm, requestOptions)
                })
            }
        }, err= > {
            errorhandle(err, reject, option, vm)
        }).catch(function (err) {
            errorhandle(err, reject, option, vm)
        })
    })

}

// Process the response information
function responseInfoHandle (resInfo, resolve, reject, option, vm) {
    // Whether the request was successful
    let isSuccess = resInfo.retCode === '200'
    / / status code
    let code = resInfo.retCode
    // Description
    let message = resInfo.retMsg || 'Request failed! '
    / / data
    let resData = resInfo.data || {}
    if (isSuccess) { // The request succeeded
        console.log(` [${option.method || 'POST'}]${option.url}Request successful! \n Request parameter: ', option.data, '\n Response result :', resInfo)
        resolve(resData)
    } else { // The service is abnormal
        console.error(` [${option.method} || 'POST']${option.url}Request failed! \n Request parameter: ', option.data, '\n Response result :', resInfo)
        let err = new BusinessError(code, message, resData)
        errorhandle(err, reject, option, vm)
    }
}

// Get the response information json object

function getResponseInfo (res) {
    return new Promise((resolve, reject) = > {
        // The information returned
        let resInfo = res.data
        if (resInfo instanceof Blob) {
            const reader = new FileReader()
            reader.readAsText(resInfo, 'utf-8')
            reader.onload = () = > {
                resInfo = JSON.parse(reader.result)
                resolve(resInfo)
            }
        } else {
        resolve(resInfo)
        }
    })
}

/* Exception handling */
function errorhandle (err, reject, option, vm) {
    let error = null
    if (err.name === 'BusinessError') {
        error = err
    } else {
        console.error(option.url, 'Request failed! ', err.code, err)
        error = new SystemError(500.'Very sorry, the system error, please try again later! ')}console.log('error = ', error)
    if (vm) {
        if (error.name === 'BusinessError') { // The service is abnormal
            // No permissions
            if (error.code === 'xxx') {
                error.ignore = true
                if(! isShowUnauthorized) { vm.$popupAlert({title: 'tip'.message: 'Not logged in or session expired, please log in again! '.width: 330.height: 180.btnText: 'Log in again'.onOK: () = > {
                            isShowUnauthorized = false // Whether to display the re-login dialog box set to true
                            // The login page is displayed. After the login succeeds, the system switches to the original path
                            vm.$router.push({ name: 'login'.params: { fromPath: vm.$route.fullPath } })
                            vm.$eventBus.$emit('NO_AUTH_EVENT')
                        }
                    })
                    isShowUnauthorized = true // Whether to display the re-login dialog box set to true
                }
                error.ignore = true
            } else if(option.toastError ! = =false) {
                vm.$toast({ type: 'error'.message: error.message })
            }
        } else { // The system is abnormal
            vm.$toast('Network exception! ')
        }
    }
    reject(error)
}

export default {
    baseUrl,
    http,
    post,
    get,
    download
}
Copy the code

Apiplugin.js, encapsulated as a plugin plug-in

import Vue from 'vue'
import api from '@/assets/js/api.js'

export default {
    install () {
        Vue.prototype.$api = api
    }
}
Copy the code

Main.js, the injection plug-in

import ApiPlugin from './plugins/apiPlugin.js'

// Background interface plug-in
Vue.use(ApiPlugin)
Copy the code

Use Cases:

  • download
this.$api.download({
    url: '/xxx/xxx/xxx'.data: params
}, this)

Copy the code
  • get
this.$api.get({
    url: `/xxx/xxx/xx`.data: params
}, this).then((res) = > {
    console.log(res)
})
Copy the code
  • post
this.$api.post({
    url: '/api/basicList/query'.data: params
}, this).then(res= >{})Copy the code

The encapsulation of Axios is almost complete