在TypeScript項(xiàng)目中搭配Axios封裝后端接口調(diào)用
前言
本來(lái)是想發(fā) next.js 開發(fā)筆記的,結(jié)果發(fā)現(xiàn)里面涉及了太多東西,還是拆分出來(lái)發(fā)吧~
本文記錄一下在 TypeScript 項(xiàng)目里封裝 axios 的過(guò)程,之前在開發(fā) StarBlog-Admin 的時(shí)候已經(jīng)做了一次封裝,不過(guò)那時(shí)是 JavaScript ,跟 TypeScript 還是有些區(qū)別的。
另外我在跟著 next.js 文檔開發(fā)的時(shí)候,注意到官方文檔推薦使用 @tanstack/react-query
來(lái)封裝請(qǐng)求類的操作,淺看了一下文檔之后感覺(jué)很不錯(cuò),接下來(lái)我會(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)系也不是很大,不過(guò)因?yàn)?axios 封裝里面需要用到,所以我也一并貼出來(lái)吧。
創(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(); } /** * 檢查登錄是否過(guò)期 * @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í)候看看有沒(méi)有錯(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 本身做什么修改,我感覺(jué)比之前用 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 似乎沒(méi)法用 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ù),先來(lái)回顧一下axios的基本使用,怎么發(fā)送一個(gè)請(qǐng)求,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2023-10-10js實(shí)現(xiàn)鼠標(biāo)滾輪控制圖片縮放效果的方法
這篇文章主要介紹了js實(shí)現(xiàn)鼠標(biāo)滾輪控制圖片縮放效果的方法,涉及onmousewheel事件及javascript操作圖片的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02深入了解JavaScript中遞歸的理解與實(shí)現(xiàn)
本文將通過(guò)遞歸的經(jīng)典案例:求斐波那契數(shù)來(lái)講解遞歸,通過(guò)畫遞歸樹的方式來(lái)講解其時(shí)間復(fù)雜度和空間復(fù)雜度以及遞歸的執(zhí)行順序,感興趣的可以了解一下2022-06-06JavaScript學(xué)習(xí)小結(jié)(一)——JavaScript入門基礎(chǔ)
本教程比較適合javascript初學(xué)者,對(duì)javascript基本知識(shí)的小結(jié)包括變量,基本類型等知識(shí)點(diǎn),需要的朋友一起來(lái)學(xué)習(xí)吧2015-09-09ajax如何實(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ù),通過(guò)在后臺(tái)與服務(wù)器進(jìn)行少量數(shù)據(jù)交換,AJAX 可以使網(wǎng)頁(yè)實(shí)現(xiàn)異步更新,本篇文章給大家介紹ajax如何實(shí)現(xiàn)頁(yè)面局部跳轉(zhuǎn)與結(jié)果返回,感興趣的朋友一起來(lái)學(xué)習(xí)2015-08-08使用InstantClick.js讓頁(yè)面提前加載200ms
本篇文章主要介紹了使用InstantClick.js讓頁(yè)面提前加載200ms,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09IE6-IE9不支持table.innerHTML的解決方法分享
讓ie6-ie9支持table.innerHTML,其實(shí)這里只是對(duì)table做了處理,對(duì)其他不支持的元素可以用類似的方案2012-09-09JavaScript實(shí)現(xiàn)前端倒計(jì)時(shí)效果
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)前端倒計(jì)時(shí)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-02-02