TS 完全指南之实战:封装 axios 和 带过期时间的 localStorage(七)
实战:axios
- 支持请求和响应拦截器
- 支持取消请求和取消全部请求的功能
- 提供了 GET、POST、PUT、DELETE 四种请求方法
import axios from "axios"
import type { AxiosInstance, AxiosResponse, InternalAxiosRequestConfig, AxiosRequestConfig } from "axios"
class Request {
// Axios 实例
instance: AxiosInstance
// 存放取消请求控制器
abortControllerMap: Map<string, AbortController>
constructor(config: AxiosRequestConfig) {
// 创建 Axios 实例
this.instance = axios.create(config)
// 存储取消请求的控制器
this.abortControllerMap = new Map()
// 添加请求拦截器
this.instance.interceptors.request.use(
(res: InternalAxiosRequestConfig) => {
// 创建取消请求的控制器
const controller = new AbortController()
// 获取请求的 url
const url = res.url || ""
// 将控制器存储到 Map 中
res.signal = controller.signal
this.abortControllerMap.set(url, controller)
return res
},
(err: any) => err
)
// 添加响应拦截器
this.instance.interceptors.response.use(
(res: AxiosResponse) => {
// 获取响应的 url
const url = res.config.url || ""
// 从 Map 中删除对应的控制器
this.abortControllerMap.delete(url)
return res.data
},
(err: any) => err // 响应拦截器错误处理函数
)
}
// 发送请求的方法,返回 Promise 对象
request<T>(config: AxiosRequestConfig<T>): Promise<T> {
return new Promise((resolve, reject) => {
this.instance
.request(config)
.then(res => {
resolve(res as T)
})
.catch((err: any) => {
reject(err)
})
})
}
// 取消全部请求
cancelAllRequest() {
for (const controller of this.abortControllerMap.values()) {
controller.abort()
}
// 清空 Map
this.abortControllerMap.clear()
}
// 取消指定的请求
cancelRequest(url: string | string[]) {
// 将参数转换为数组
const urlList = Array.isArray(url) ? url : [url]
urlList.forEach(_url => {
// 根据 url 获取对应的控制器并取消请求
this.abortControllerMap.get(_url)?.abort()
// 从 Map 中删除对应的控制器
this.abortControllerMap.delete(_url)
})
}
// 发送 GET 请求的方法,返回 Promise 对象
async get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
return this.request<T>({ ...config, method: "get", url })
}
// 发送 POST 请求的方法,返回 Promise 对象
async post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
return this.request<T>({ ...config, method: "post", url, data })
}
// 发送 PUT 请求的方法,返回 Promise 对象
async put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
return this.request<T>({ ...config, method: "put", url, data })
}
// 发送 DELETE 请求的方法,返回 Promise 对象
async delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
return this.request<T>({ ...config, method: "delete", url })
}
}
const myRequest = new Request({
baseURL: "https://www.fastmock.site/mock/13089f924ad68903046c5a61371475c4",
timeout: 10000,
})
export default myRequest
使用:
<script setup lang="ts">
import myRequest from "./axios"
import { onMounted } from "vue"
interface Req {
name: string
}
interface Res {
code: string
data: {
userName: string
}
}
const getData = (data: Req) => {
return myRequest.request<Res>({
url: "/api/user/login",
method: "POST",
data
})
}
onMounted(async () => {
const res = await getData({
name: "云牧"
})
console.log(res)
})
</script>
实战:localStorage
interface LocalStorageItem<T> {
value: T // 存储的值
expire: number | null // 过期时间,如果为 null 则表示永不过期
}
class LocalStorage {
private static instance: LocalStorage // 单例模式,保证只有一个实例
private storage: Storage // localStorage 对象
private constructor() {
this.storage = window.localStorage // 获取 localStorage 对象
}
public static getInstance(): LocalStorage {
if (!LocalStorage.instance) {
// 如果实例不存在,则创建一个新实例
LocalStorage.instance = new LocalStorage()
}
return LocalStorage.instance // 返回实例
}
public setItem<T>(key: string, value: T, expire?: number): void {
const item: LocalStorageItem<T> = {
value: value, // 存储的值
expire: expire ? new Date().getTime() + expire : null, // 过期时间
}
this.storage.setItem(key, JSON.stringify(item)) // 将对象序列化为字符串并存储到 localStorage 中
}
public getItem<T>(key: string): T | null {
const itemStr = this.storage.getItem(key) // 获取存储的字符串
if (itemStr) {
// 如果字符串存在
const item: LocalStorageItem<T> = JSON.parse(itemStr) // 将字符串反序列化为对象
if (!item.expire || new Date().getTime() < item.expire) {
// 如果没有过期或者还没有过期
return item.value // 返回存储的值
} else {
this.storage.removeItem(key) // 如果已经过期,则删除该项
}
}
return null // 如果不存在或者已经过期,则返回 null
}
public removeItem(key: string): void {
this.storage.removeItem(key) // 删除指定的项
}
public clear(): void {
this.storage.clear() // 清空 localStorage
}
}
export default LocalStorage.getInstance() // 导出 LocalStorage 实例
使用:
<script lang="ts" setup>
import storage from "./storage"
// 存储数据
storage.setItem("name", "黛玉", 60 * 60 * 1000) // 存储一个过期时间为 1 小时的数据
storage.setItem("person", { name: "云牧" }, 60 * 60 * 1000) // 存储一个过期时间为 1 小时的数据
interface Person {
name: string
}
// 获取数据
const name = storage.getItem<string>("name")
const person = storage.getItem<Person>("person")
console.log(name) // 黛玉
console.log(person.name) // 云牧
// 删除数据
storage.removeItem("name")
// 清空所有数据
storage.clear()
</script>
转载自:https://juejin.cn/post/7212986537776431162