This article has participated in the “Newcomer Creation Ceremony” activity, and started the road of digging gold creation together
As Typescript becomes more popular and many projects incorporate Ts, it is imperative that Axios be wrapped with Ts, one person wrapped, for the benefit of all
Let’s talk about why we should use Ts and what advantages Ts has over Js.
Typescript characteristics
- Turing complete. (Not sure what that means, though)
- Progressive type system, all type annotations are optional, both angel and demon any type. (Haskell bull Colliot called the TS type system vulnerability)
- Support for local type inference.
- Rich type-level calculations, such as index types, mapped types, conditional types, etc.
- Supports duck types. (Or structural subtypes?)
- Js supports convenient object literal types, strings and numbers, and Boolean literal types just as it supports object literals.
- An empty safe.
- Type analysis based on control flow.
There’s also support for type aliases, generics, covariant contravariant doubles, and more…
Advantages:
First, static type checking can be an early fail, meaning that if you write code that doesn’t get executed, if a type mismatch occurs while you’re writing it, the language will catch it at compile time (and interpret execution, too, before it runs). For large applications, the test debug branch is difficult to cover, and much of the code may not be executed under all conditions. And if your code is so simple that any changes can be made to the UI, which is really not relevant to a large application, then static type checking really doesn’t work.
Second, static typing is friendly to reading code. For example, let’s take jQuery API Documentation, which everyone likes to use in jquery.Ajax. In this Documentation, the only parameter Settings of type Object is explained in detail, and it’s so complicated, If we were to look at the function declaration without documentation, it would be impossible for anyone to guess this usage correctly. For large applications, where methods are numerous and invocation relationships are complex, it is impossible for someone to meticulously document every function, so static typing is an important reminder and constraint. And if you have code like jQuery where all the functions are apis, there are no internal functions at all, and the logic seems obvious, which is really not relevant for a large application, then static typing really doesn’t help you read the code, right
Conclusion:
- Ts provides type determination and notifies errors early rather than after Js runs
- High code friendliness
Axios encapsulation
This encapsulation of Axios also implements a throttle-like effect, filtering out subsequent repeated requests
Axios encapsulation
Import axios, {AxiosRequestConfig, AxiosResponse, AxiosInstance} from 'axios'; // import { setToken, getToken, getTokenKey, removeToken, } from "./cookie"; import { addPending, removePending, checkRequest } from './pending'; const showStatus = (status: number) => { let message = ''; Switch (status) {case 400: message = 'error (400)'; break; Case 401: message = 'not authorized, please login (401) again '; break; Case 403: message = 'access denied (403)'; break; Case 404: message = '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 '; 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 administrator! `; }; export class Interceptors { instance: AxiosInstance; Constructor () {this.instance = axios.constructor () ({baseURL: import.meta.env.VITE_API_BASE_URL as string, // 30 * 1000, withCredentials: true, headers: { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/json; charset=utf-8', }, }); this.setupInterceptors(); } / / initializes the interceptor setupInterceptors () {/ / request interface interceptor enclosing instance. The interceptors. Request. Use ((config: AxiosRequestConfig) => { if (! CheckRequest (config)) {// If the request is not pending, add pending // If it is, // if (getToken()) {// config.headers[getTokenKey()] = getToken(); // } return config; }, () => {// error thrown to business code const error = {data: {MSG: 'server exception, please contact the administrator! '}}; return Promise.resolve(error); }); / / response interceptor enclosing instance. The interceptors. Response. Use ((response: AxiosResponse) = > {removePending (response); Return response.data; // Return response.data; }, (error: any) => { let msg; let code = -1; if (axios.isCancel(error)) { msg = ''; code = -2; } else { const { status } = error? .response; If (status < 200 | | status > = 300) {/ / processing HTTP error, to the business code MSG = showStatus (status); } } return Promise.resolve({ msg, code }); }); } getInterceptors() {return this.instance; }}Copy the code
Export the HTTP
Import {AxiosPromise} from 'axios'; import { Interceptors } from './axios'; import { message } from 'ant-design-vue'; export interface HttpRequest { method? : string url: string data? : any timeout? : number} // Export interface HttpResponse {code: number data: any MSG: Export class HttpServer {axios: any; Constructor () {this.axios = new Interceptors().getInterceptors(); } // Request (config: HttpRequest): AxiosPromise { return new Promise((resolve, reject) => { this.axios(config).then((res: HttpResponse) => { if (res.code === 0) { resolve(res? .data); } else if (res.code === -2) {// Multiple requests to cancel console.log(' multiple requests. '); } else { const msg = res? The MSG | | 'system is busy, please try again later; message.error(msg); reject(msg); } }) .catch((err: any) => { err? .msg && message.error(err? .msg); reject(err); }); }); } } const http = new HttpServer(); export default http;Copy the code
Implementation to heavy
// pending. Ts // implement re-import axios, {AxiosRequestConfig} from 'axios'; / / CancelToken instructions/reference articles/https://segmentfault.com/a/1190000039806000 / https://github.com/axios/axios/statement a Map Export const Pending = new Map(); export const Pending = new Map(); export const getKey = (config: AxiosRequestConfig) => JSON.stringify([config.method, config.url, config.params, config.data]); /** * add request * @param {Object} config */ export const addPending = (config: AxiosRequestConfig): void => { const url = getKey(config); // eslint-disable-next-line no-param-reassign config.cancelToken = config.cancelToken || new axios.CancelToken((cancel) => { if (! Pending.has (url)) {// If there is no current request in pending, add it to pending.set(URL, cancel); }}); }; @param {Object} config */ export const removePending = (config: AxiosRequestConfig): void => { const url = getKey(config); If (pending.has(url)) {// If the current request flag exists in pending, cancel the current request and remove const cancel = pending.get(url); cancel(url); pending.delete(url); }}; /** * clearPending requests (called when routing jumps) */ export const clearPending = (): void => { for (const [url, cancel] of pending) { cancel(url); } pending.clear(); }; Export const checkRequest = (config: AxiosRequestConfig): Boolean => {const url = getKey(config); if (pending.has(url)) { new axios.CancelToken((cancel) => { cancel(url); }) return true; } else return false; }Copy the code
// cookie.ts
import Cookies from 'js-cookie';
const tokenKey = 'token';
export const getToken = () => Cookies.get(tokenKey);
export const getTokenKey = () => tokenKey;
export const setToken = (token: string) => Cookies.set(tokenKey, token);
export const removeToken = () => Cookies.remove(tokenKey);
Copy the code
Undo all requests on a route jump
import { createRouter, createWebHistory, RouteRecordRaw} from 'vue-router' import Login from '@/views/Login/ login. vue' // Import clearPending function exposed in AXIos import { clearPending } from "@/utils/http/pending" .... . . const router = createRouter({ history: CreateWebHistory (process.env.base_URL), routes}) router. BeforeEach ((to, from, next) => { Clear all requests clearPending() //... next() }) export default routerCopy the code
Request for example
Request ({url: / API/XXX/XXX, method: 'get', data: {username, password}}). Then ((res: any) => {... }).catch((err) => { ... }) // async/await // async const res = await http.request({url: / API/XXX/XXX, method: 'get', data: { username, password } });Copy the code
Refer to the link
What are the benefits of TypeScript? What’s the difference from JavaScript?
Axios instructions
Vue3+TypeScript encapsulates AXIOS and makes request calls