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

Detailed tutorial on installing and configuring MySQL 5.7.20 under Centos7

1. Download the MySQL 5.7 installation package fr...

Docker uses busybox to create a base image

The first line of a Docker image starts with an i...

Use vue2+elementui for hover prompts

Vue2+elementui's hover prompts are divided in...

Example code for implementing stacked carousel effect with HTML+CSS+JS

Effect: When the slideshow moves in one direction...

How to configure Nginx load balancing

Table of contents Nginx load balancing configurat...

Django+vue registration and login sample code

register The front-end uses axios in vue to pass ...

Vue implements the full selection function

This article example shares the specific code of ...

Solution - BASH: /HOME/JAVA/JDK1.8.0_221/BIN/JAVA: Insufficient permissions

1) Enter the folder path where the jdk file is st...

HTML form component example code

HTML forms are used to collect different types of...

Detailed explanation of how to use $props, $attrs and $listeners in Vue

Table of contents background 1. Document Descript...

Creating a Secondary Menu Using JavaScript

This article example shares the specific code of ...

HTML Nine-grid Layout Implementation Method

Diversifying website layouts is our front-end spe...

In-depth analysis of nginx+php-fpm service HTTP status code 502

One of our web projects has seen an increase in t...

Example of using Dockerfile to build an nginx image

Introduction to Dockerfile Docker can automatical...