Vue3+TypeScript encapsulates axios and implements request calls

Vue3+TypeScript encapsulates axios and implements request calls

No way, no way, it turns out that there are people who have never heard of TypeScript in 2021? Although using TypeScript in a project will increase some development costs in the short term, for projects that require long-term maintenance, TypeScript can reduce their maintenance costs. Using TypeScript increases the readability and maintainability of the code, and it has a relatively active community. As it is the trend of the big front-end, let's get started~

Use TypeScript to encapsulate the basic axios library

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 = 'Unauthorized, please log in again (401)'
      break
    case 403:
      message = 'Access Denied (403)'
      break
    case 404:
      message = 'Request error (404)'
      break
    case 408:
      message = 'Request timeout (408)'
      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 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({
  // Joint debugging // 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 request cross-site access control withCredentials: true,
  timeout: 30000,
  transformRequest: [(data) => {
    data = JSON.stringify(data)
    return data
  }],
  validateStatus() {
    // Using async-await, handling reject situations is cumbersome, so all return resolve, handle exceptions 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 abnormality, please contact the 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 them to 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 timeout or server exception, please check the network or contact the administrator! '
    ElMessage.error(error.data.msg)
  }
  return Promise.reject(error)
})

export default service

Cancel multiple duplicate request versions

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 identifier and cancellation function of each request const pending = new Map()
/**
 * 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 the current request does not exist 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, you need to cancel the current request and remove const cancel = pending.get(url)
    cancel(url)
    pending.delete(url)
  }
}

/**
 * Clear pending requests (called when routing redirects)
 */
export const clearPending = () => {
  for (const [url, cancel] of pending) {
    cancel(url)
  }
  pending.clear()
}

// Request interceptor service.interceptors.request.use((config: AxiosRequestConfig) => {
  removePending(config) // Before the request starts, check and cancel the previous request 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 abnormality, please contact the administrator! '
  return Promise.resolve(error)
})

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

  removePending(response) // After the request is completed, remove this request const status = response.status
  let msg = ''
  if (status < 200 || status >= 300) {
    // Handle http errors and throw them to 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 timeout or server exception, please check the network or contact the administrator! '
    ElMessage.error(error.data.msg)
  }
  return Promise.reject(error)
})

export default service

Cancel all requests when routing

Add in the routing 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) => {
  // Before redirecting, clear all requests clearPending()
  // ...
  next()
})

export default router

Use the encapsulated axios request library

Encapsulated response format

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

Encapsulation interface method

For example, to encapsulate the User interface, the code is as follows~

import Axios from './axios'
import { HttpResponse } from '@/@types'
/**
 * @interface loginParams - login parameters * @property {string} username - username * @property {string} password - user password */
interface LoginParams {
  username: string
  password: string
}
//Encapsulate the interface method of User type export class UserService {
  /**
   * @description Query User information* @param {number} teamId - the team ID 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
      },
    })
  }
}

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()">Login</button>
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs } from 'vue'
//Import 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>

This is the end of this article about Vue3+TypeScript encapsulating axios and implementing request calls. For more relevant Vue3+TypeScript encapsulating axios content, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • How to encapsulate axios request with vue
  • Vue application example code based on axios request encapsulation
  • How to encapsulate axios in Vue project (unified management of http requests)
  • Vue+axios encapsulates requests to separate the front and back ends
  • Steps for Vue to encapsulate Axios requests and interceptors
  • How to use Axios to encapsulate http requests in Vue projects
  • Vue axios repeated click cancel the last request encapsulation method
  • Encapsulation request of axios in vue project

<<:  Linux implements automatic and scheduled backup of MySQL database every day

>>:  Tomcat+Mysql high concurrency configuration optimization explanation

Recommend

ElementUI implements the el-form form reset function button

Table of contents Business scenario: Effect demon...

Detailed example of HTML element blocking Flash

Copy code The code is as follows: wmode parameter...

Detailed tutorial for downloading, installing and configuring MySQL 5.7.27

Table of contents 1. Download steps 2. Configure ...

How to install and uninstall open-vswitch in Linux

1. Compile and install ovs from source code: Inst...

React implements multi-component value transfer function through conetxt

The effect of this function is similar to vue的pro...

Detailed explanation of JS ES6 coding standards

Table of contents 1. Block scope 1.1. let replace...

Innodb system table space maintenance method

Environmental Description: There is a running MyS...

Several magical uses of JS ES6 spread operator

Table of contents 1. Add attributes 2. Merge mult...

MySQL slave library Seconds_Behind_Master delay summary

Table of contents MySQL slave library Seconds_Beh...

MySQL index usage instructions (single-column index and multi-column index)

1. Single column index Choosing which columns to ...