在TypeScript項(xiàng)目中搭配Axios封裝后端接口調(diào)用
前言
本來是想發(fā) next.js 開發(fā)筆記的,結(jié)果發(fā)現(xiàn)里面涉及了太多東西,還是拆分出來發(fā)吧~
本文記錄一下在 TypeScript 項(xiàng)目里封裝 axios 的過程,之前在開發(fā) StarBlog-Admin 的時(shí)候已經(jīng)做了一次封裝,不過那時(shí)是 JavaScript ,跟 TypeScript 還是有些區(qū)別的。
另外我在跟著 next.js 文檔開發(fā)的時(shí)候,注意到官方文檔推薦使用 @tanstack/react-query 來封裝請(qǐng)求類的操作,淺看了一下文檔之后感覺很不錯(cuò),接下來我會(huì)在項(xiàng)目里實(shí)踐。
定義配置
先創(chuàng)建一個(gè) global 配置,src/utilities/global.ts
export default class Global {
static baseUrl = process.env.NEXT_PUBLIC_BASE_URL
}
這是在 next.js 項(xiàng)目,可以用 next 規(guī)定的環(huán)境變量,其他項(xiàng)目可以自行修改。
封裝 auth
認(rèn)證這部分跟 axios 有點(diǎn)關(guān)系,但關(guān)系也不是很大,不過因?yàn)?axios 封裝里面需要用到,所以我也一并貼出來吧。
創(chuàng)建 src/utilities/auth.ts 文件
/**
* 登錄信息
*/
export interface LoginProps {
token: string
username: string
expiration: string
}
/**
* 認(rèn)證授權(quán)工具類
*/
export default abstract class Auth {
static get storage(): Storage | null {
if (typeof window !== 'undefined') {
return window.localStorage
}
return null
}
/**
* 檢查是否已登錄
* @return boolean
*/
public static isLogin() {
let token = this.storage?.getItem('token')
let userName = this.storage?.getItem('user')
if (!token || token.length === 0) return false
if (!userName || userName.length === 0) return false
return !this.isExpired();
}
/**
* 檢查登錄是否過期
* @return boolean
*/
public static isExpired = () => {
let expiration = this.storage?.getItem('expiration')
if (expiration) {
let now = new Date()
let expirationTime = new Date(expiration)
if (now > expirationTime) return true
}
return false
}
/**
* 讀取保存的token
* @return string
*/
public static getToken = () => {
return this.storage?.getItem('token')
}
/**
* 保存登錄信息
* @param props
*/
public static login = (props: LoginProps) => {
this.storage?.setItem('token', props.token)
this.storage?.setItem('user', props.username)
this.storage?.setItem('expiration', props.expiration)
}
/**
* 注銷
*/
public static logout = () => {
this.storage?.removeItem('token')
this.storage?.removeItem('user')
this.storage?.removeItem('expiration')
}
}
跟認(rèn)證有關(guān)的邏輯我都放在 Auth 類中了
為了在 next.js 中可以愉快使用,還得做一些特別的處理,比如我增加了 storage 屬性,讀取的時(shí)候先判斷 window 是否存在。
封裝 axios
關(guān)于 API 的代碼我都放在 src/services 目錄下。
創(chuàng)建 src/services/api.ts 文件,代碼比較長(zhǎng),分塊介紹,可以看到所有配置相比之前 JavaScript 版本的都多了配置,對(duì) IDE 自動(dòng)補(bǔ)全非常友好。
先 import
import axios, {AxiosInstance, AxiosRequestConfig, AxiosResponse, CreateAxiosDefaults} from "axios";
import Global from '@/utilities/global'
import Auth from "@/utilities/auth";
Axios 配置
定義一下 axios 的配置
const config: CreateAxiosDefaults<any> = {
method: 'get',
// 基礎(chǔ)url前綴
baseURL: `${Global.baseUrl}/`,
// 請(qǐng)求頭信息
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
// 參數(shù)
data: {},
// 設(shè)置超時(shí)時(shí)間
timeout: 10000,
// 攜帶憑證
withCredentials: true,
// 返回?cái)?shù)據(jù)類型
responseType: 'json'
}
統(tǒng)一接口返回值
設(shè)置統(tǒng)一的接口返回值,這個(gè)和我在 StarBlog 后端里封裝的那套是一樣的,現(xiàn)在基本是我寫后端的標(biāo)準(zhǔn)返回值了,同時(shí)也發(fā)布了 CodeLab.Share nuget包,可以快捷的引入這個(gè)統(tǒng)一的返回值組件。
// 統(tǒng)一接口返回值
export interface ApiResponse {
data: any
errorData: any
message: string
statusCode: number
successful: boolean
}
定義 ApiClient
最后就是定義了 ApiClient 類,有點(diǎn)模仿 C# 的 HttpClient 內(nèi)味了
這里面用到了 axios 的攔截器,發(fā)起請(qǐng)求的時(shí)候給 header 加上認(rèn)證信息,返回的時(shí)候看看有沒有錯(cuò)誤,如果是 401 unauthorized 的話就跳轉(zhuǎn)到登錄頁(yè)面。
export class ApiClient {
private readonly api: AxiosInstance
constructor() {
this.api = axios.create({
...config,
})
this.api.interceptors.request.use(
config => {
config.headers.Authorization = `Bearer ${Auth.getToken()}`
return config
},
error => {
return error
})
this.api.interceptors.response.use(
response => {
return response
},
error => {
let reason = error
if (error && error.response) {
if (error.response.data) {
reason = error.response.data
if (!reason.message) reason.message = error.message
}
if (error.response.status === 401) {
location.href = '/login'
}
}
return Promise.reject(reason)
}
)
}
public request(options: AxiosRequestConfig): Promise<ApiResponse> {
return new Promise((resolve, reject) => {
this.api(options).then((res: AxiosResponse<ApiResponse>) => {
resolve(res.data)
return false
}).catch(error => {
reject(error)
})
})
}
}
export const api = new ApiClient()
export default api代碼比之前我在 StarBlog-Admin 里的簡(jiǎn)單一些,我要盡可能用較少的代碼實(shí)現(xiàn)需要的功能。
編寫具體接口調(diào)用
所有的接口調(diào)用我都寫成 service (后端思維是這樣的)
這里以發(fā)短信接口為例
創(chuàng)建 src/services/common.ts 文件,從剛才定義的 api.ts 里面引入 ApiClient 的對(duì)象,直接調(diào)用 request 方法就完事了。
參數(shù)類型是 AxiosRequestConfig ,不對(duì) axios 本身做什么修改,我感覺比之前用 Antd Pro 魔改的接口舒服一些。
import {api} from './api'
export class SmsChannel {
static local = 0
static aliyun = 1
static tencent = 2
}
export default abstract class CommonService {
public static getSmsCode(phone: string, channel: number = SmsChannel.local) {
return api.request({
url: `api/common/getSmsCode`,
params: {phone, channel}
})
}
}小結(jié)
這樣封裝完比之前 StarBlog-Admin 的舒服很多,可惜之前那個(gè)項(xiàng)目用的是 vue2.x 似乎沒法用 TypeScript。
就這樣吧,大部分內(nèi)容還是在 next.js 開發(fā)筆記中。
參考資料
到此這篇關(guān)于在TypeScript項(xiàng)目中搭配Axios封裝后端接口調(diào)用的文章就介紹到這了,更多相關(guān)Axios封裝后端接口調(diào)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解析為什么axios會(huì)有params和data兩個(gè)參數(shù)
本文給大家分享為什么axios會(huì)有params和data兩個(gè)參數(shù),先來回顧一下axios的基本使用,怎么發(fā)送一個(gè)請(qǐng)求,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2023-10-10
js實(shí)現(xiàn)鼠標(biāo)滾輪控制圖片縮放效果的方法
這篇文章主要介紹了js實(shí)現(xiàn)鼠標(biāo)滾輪控制圖片縮放效果的方法,涉及onmousewheel事件及javascript操作圖片的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02
深入了解JavaScript中遞歸的理解與實(shí)現(xiàn)
本文將通過遞歸的經(jīng)典案例:求斐波那契數(shù)來講解遞歸,通過畫遞歸樹的方式來講解其時(shí)間復(fù)雜度和空間復(fù)雜度以及遞歸的執(zhí)行順序,感興趣的可以了解一下2022-06-06
JavaScript學(xué)習(xí)小結(jié)(一)——JavaScript入門基礎(chǔ)
本教程比較適合javascript初學(xué)者,對(duì)javascript基本知識(shí)的小結(jié)包括變量,基本類型等知識(shí)點(diǎn),需要的朋友一起來學(xué)習(xí)吧2015-09-09
ajax如何實(shí)現(xiàn)頁(yè)面局部跳轉(zhuǎn)與結(jié)果返回
AJAX即“Asynchronous Javascript And XML”(異步JavaScript和XML),是指一種創(chuàng)建交互式網(wǎng)頁(yè)應(yīng)用的網(wǎng)頁(yè)開發(fā)技術(shù),通過在后臺(tái)與服務(wù)器進(jìn)行少量數(shù)據(jù)交換,AJAX 可以使網(wǎng)頁(yè)實(shí)現(xiàn)異步更新,本篇文章給大家介紹ajax如何實(shí)現(xiàn)頁(yè)面局部跳轉(zhuǎn)與結(jié)果返回,感興趣的朋友一起來學(xué)習(xí)2015-08-08
使用InstantClick.js讓頁(yè)面提前加載200ms
本篇文章主要介紹了使用InstantClick.js讓頁(yè)面提前加載200ms,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09
IE6-IE9不支持table.innerHTML的解決方法分享
讓ie6-ie9支持table.innerHTML,其實(shí)這里只是對(duì)table做了處理,對(duì)其他不支持的元素可以用類似的方案2012-09-09
JavaScript實(shí)現(xiàn)前端倒計(jì)時(shí)效果
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)前端倒計(jì)時(shí)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-02-02

