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