Come on, come on, there are people in 2021 who haven’t even heard of TypeScript? While using TypeScript in projects increases development costs in the short term, it reduces maintenance costs for projects that require long-term maintenance. Using TypeScript increases code readability and maintainability, and has a vibrant community. So start looking

Encapsulate the base AXIOS library in TypeScript

The code is as follows:

// http.ts
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'
import { ElMessage } from "element-plus"

const showStatus = (status: number) = > {
  let message = ' '
  switch (status) {
    case 400:
      message = 'Request error (400)'
      break
    case 401:
      message = 'Not authorized, please log back in (401)'
      break
    case 403:
      message = 'Access denied (403)'
      break
    case 404:
      message = 'Request error (404)'
      break
    case 408:
      message = 'Request timed out (408)'
      break
    case 500:
      message = 'Server error (500)'
      break
    case 501:
      message = 'Service Not realized (501)'
      break
    case 502:
      message = 'Network Error (502)'
      break
    case 503:
      message = 'Service unavailable (503)'
      break
    case 504:
      message = 'Network Timeout (504)'
      break
    case 505:
      message = 'HTTP version not supported (505)'
      break
    default:
      message = 'Connection error (${status})! `
  }
  return `${message}Please check the network or contact the administrator! `
}

const service = axios.create({
  / / alignment
  // baseURL: process.env.NODE_ENV === 'production' ? `/` : '/api',
  baseURL: "/api".headers: {
    get: {
      'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
    },
    post: {
      'Content-Type': 'application/json; charset=utf-8'}},// Whether to control requests for cross-site access
  withCredentials: true.timeout: 30000.transformRequest: [(data) = > {
    data = JSON.stringify(data)
    return data
  }],
  validateStatus() {
    // Use async-await to handle reject, so return resolve to handle exception in business code
    return true
  },
  transformResponse: [(data) = > {
    if (typeof data === 'string' && data.startsWith('{')) {
      data = JSON.parse(data)
    }
    return data
  }]
  
})

// Request interceptor
service.interceptors.request.use((config: AxiosRequestConfig) = > {
  // Get the token and add it to the request header
  let token = localStorage.getItem('token')
  if(token){
    config.headers.Authorization = `${token}`;
  }
  return config
}, (error) = > {
  // Error thrown to business code
  error.data = {}
  error.data.msg = 'Server exception, please contact administrator! '
  return Promise.resolve(error)
})

// Response interceptor
service.interceptors.response.use((response: AxiosResponse) = > {
  const status = response.status
  let msg = ' '
  if (status < 200 || status >= 300) {
    // Handle HTTP errors and throw into the business code
    msg = showStatus(status)
    if (typeof response.data === 'string') {
      response.data = { msg }
    } else {
      response.data.msg = msg
    }
  }
  return response
}, (error) = > {
  if (axios.isCancel(error)) {
    console.log('repeated request: ' + error.message)
  } else {
    // handle error code
    // Error thrown to business code
    error.data = {}
    error.data.msg = 'Request timed out or server exception, please check network or contact administrator! '
    ElMessage.error(error.data.msg)
  }
  return Promise.reject(error)
})

export default service
Copy the code

Cancels versions of requests that are repeated multiple times

Add the following code to the above code:

// http.ts
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'
import qs from "qs"
import { ElMessage } from "element-plus"

// Declare a Map to store the identity and cancel functions for each request
const pending = new Map(a)/** * Add request *@param {Object} config 
 */
const addPending = (config: AxiosRequestConfig) = > {
  const url = [
    config.method,
    config.url,
    qs.stringify(config.params),
    qs.stringify(config.data)
  ].join('&')
  config.cancelToken = config.cancelToken || new axios.CancelToken(cancel= > {
    if(! pending.has(url)) {// If there is no current request in Pending, add it
      pending.set(url, cancel)
    }
  })
}
/** * Remove request *@param {Object} config 
 */
const removePending = (config: AxiosRequestConfig) = > {
  const url = [
    config.method,
    config.url,
    qs.stringify(config.params),
    qs.stringify(config.data)
  ].join('&')
  if (pending.has(url)) { // If the current request identifier exists in pending, cancel the current request and remove it
    const cancel = pending.get(url)
    cancel(url)
    pending.delete(url)
  }
}

/** * Clears requests in pending (called when a route jumps) */
export const clearPending = () = > {
  for (const [url, cancel] of pending) {
    cancel(url)
  }
  pending.clear()
}

// Request interceptor
service.interceptors.request.use((config: AxiosRequestConfig) = > {
  removePending(config) // Check and cancel the previous request before the request starts
  addPending(config) // Add the current request to Pending
  let token = localStorage.getItem('token')
  if(token){
    config.headers.Authorization = `${token}`;
  }
  return config
}, (error) = > {
  // Error thrown to business code
  error.data = {}
  error.data.msg = 'Server exception, please contact administrator! '
  return Promise.resolve(error)
})

// Response interceptor
service.interceptors.response.use((response: AxiosResponse) = > {

  removePending(response) // Remove the request after the request is complete
  const status = response.status
  let msg = ' '
  if (status < 200 || status >= 300) {
    // Handle HTTP errors and throw into the business code
    msg = showStatus(status)
    if (typeof response.data === 'string') {
      response.data = { msg }
    } else {
      response.data.msg = msg
    }
  }

  return response
}, (error) = > {
  if (axios.isCancel(error)) {
    console.log('repeated request: ' + error.message)
  } else {
    // handle error code
    // Error thrown to business code
    error.data = {}
    error.data.msg = 'Request timed out or server exception, please check network or contact administrator! '
    ElMessage.error(error.data.msg)
  }
  return Promise.reject(error)
})

export default service

Copy the code

Undo all requests on a route jump

Add the route to the route file index.ts

import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import Login from '@/views/Login/Login.vue'
// Introduce the clearPending function exposed in AXIos
import { clearPending } from "@/api/axios". . .const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

router.beforeEach((to, from, next) = > {
  // Clear all requests before jumping to the route
  clearPending()
  // ...
  next()
})

export default router
Copy the code

Use the encapsulated AXIOS request library

Encapsulated response format

// The interface response passes the format
export interface HttpResponse {
  status: number
  statusText: string
  data: {
    code: number
    desc: string
    [key: string] :any}}Copy the code

Encapsulating interface method

For example, encapsulate the User interface with the following code

import Axios from './axios'
import { HttpResponse } from '@/@types'
/ * * *@interface loginParams- Login parameters *@property {string} username- User name *@property {string} password- User password */
interface LoginParams {
  username: string
  password: string
}
// Encapsulate interface methods of type User
export class UserService {
  / * * *@description Query User information *@param {number} teamId- ID of the team to be queried *@return {HttpResponse} result* /
  static async login(params: LoginParams): Promise<HttpResponse> {
    return Axios('/api/user', {
      method: 'get'.responseType: 'json'.params: {
        ...params
      },
    })
  }

  static async resgister(params: LoginParams): Promise<HttpResponse> {
    return Axios('/api/user/resgister', {
      method: 'get'.responseType: 'json'.params: {
        ...params
      },
    })
  }
}
Copy the code

For use in projects

The code is as follows:

<template>
     <input type="text" v-model="Account" placeholder="Please enter your account number" name="username" >
     <input type="text" v-model="Password" placeholder="Please enter your password" name="username" >
     <button @click.prevent="handleRegister()">The login</button>
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs } from 'vue'
// Import the interface
import { UserService } from '@/api/user'

export default defineComponent({
  setup() {
    const state = reactive({
      Account: 'admin'./ / account
      Password: 'hhhh'./ / password
    })

    const handleLogin = async() = > {const loginParams = {
        username: state.Account,
        password: state.Password,
      }
      const res = await UserService.login(loginParams)
 	  console.log(res)
    }

    const handleRegister = async() = > {const loginParams = {
        username: state.Account,
        password: state.Password,
      }
      const res = await UserService.resgister(loginParams)
      console.log(res)
    }
    return {
      ...toRefs(state),
      handleLogin,
      handleRegister 
    }
  },
})
</script>
Copy the code