您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“ts如何封裝axios”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“ts如何封裝axios”吧!
別再用 promise
包了,好嗎?
看了一下,很多人封裝 axios
的時(shí)候都用 promise
包裝了一層,甚至更有甚者用起了 try catch
。為什么反對(duì)用 promise
包裝,因?yàn)?axios
返回的就是個(gè) promise
,脫褲子放屁,完全沒必要????‍♀?。至于 try catch
這個(gè)是用于捕獲未知錯(cuò)誤的,比如 JSON.parse
的時(shí)候,有些字符串就是無法轉(zhuǎn)換。記住一句話,濫用 try catch
和隨地大小便沒有區(qū)別。
一個(gè) request
方法梭哈,噗!我一口老血????
部分人直接就一個(gè) request
方法梭哈,所有參數(shù)與配置都寫在一起,看起來一點(diǎn)也不清晰,簡(jiǎn)潔。請(qǐng)求有多種方式,get
,post
,put...
,最合理的請(qǐng)求方式應(yīng)該是 instance[method](url, data, options)
。對(duì)應(yīng) 請(qǐng)求地址、請(qǐng)求參數(shù)、請(qǐng)求配置項(xiàng),一目了然。
擴(kuò)展我需要的請(qǐng)求,不要再 ts-ignore
了????
如果 ts-ignore
用多了,就會(huì)產(chǎn)生依賴性。不排除情況緊急急著上線,或者 類型處理 復(fù)雜的,但是在有時(shí)間的時(shí)候,還是得優(yōu)化一下,作為程序員,追求優(yōu)雅,永不過時(shí)。
求你了!把攔截器拿出來吧????
封裝的時(shí)候我們都會(huì)封裝一個(gè)請(qǐng)求類,但對(duì)應(yīng)攔截器應(yīng)該解耦出來。因?yàn)槊總€(gè)域名的攔截器處理可能不一致,寫死的話封裝請(qǐng)求類的意義也就沒有了。
接口請(qǐng)求 then
里面又判斷后端返回碼判斷請(qǐng)求是否成功,太狗血了!
看到下面這種代碼,給我難受的啊。
api.post(url, data).then((res) => { if (res.code === 1) { // ... } else { // 全局消息提示 console.error(res.message) } })
既然是一個(gè) promise
,我們就應(yīng)該知道 promise
只有成功或者失敗。then
怎么會(huì)有成功錯(cuò)誤的處理呢?then
里面就是請(qǐng)求成功,沒有什么 if else
,處理失敗去 catch
里面處理去。這么喜歡寫 if else
,你是沒寫過單元測(cè)試是吧?
OK
,吐槽了這么多,這時(shí)候肯定就有人說了,光說誰不會(huì)啊,你整一個(gè)?。????
瞧你這話說的,一點(diǎn)活沒干,還讓你白嫖了。你咋這么能呢?????
不過話說回來,我不要活在他人的評(píng)價(jià)里,我做這件事情不是因?yàn)槟愕闹S刺或者吹捧,而是我自己要做????‍????。
接下來定一下要做的事情
封裝一個(gè)請(qǐng)求類
適當(dāng)擴(kuò)展 axios
類型,為自定義配置打地基
支持自定義請(qǐng)求配置。如是否全局錯(cuò)誤提示
攔截器單獨(dú)拎出來,方便擴(kuò)展新的請(qǐng)求
// 這是 axios 請(qǐng)求類型定義,但是因?yàn)槲覀冃枰С肿远x配置,所以待會(huì)需要把它拓展一下 export interface AxiosRequestConfig<D = any> { url?: string; method?: Method | string; baseURL?: string; transformRequest?: AxiosRequestTransformer | AxiosRequestTransformer[]; transformResponse?: AxiosResponseTransformer | AxiosResponseTransformer[]; headers?: (RawAxiosRequestHeaders & MethodsHeaders) | AxiosHeaders; params?: any; paramsSerializer?: ParamsSerializerOptions; data?: D; timeout?: Milliseconds; timeoutErrorMessage?: string; withCredentials?: boolean; // ... } // 這是 axios 請(qǐng)求返回類型定義,里面類型需要處理,所以這個(gè)我們也得處理一下。 export interface AxiosResponse<T = any, D = any> { data: T; status: number; statusText: string; headers: RawAxiosResponseHeaders | AxiosResponseHeaders; // 這里的配置沒有支持拓展,所以待會(huì)也得處理一下 config: InternalAxiosRequestConfig<D>; request?: any; } // 所以我們只需要改造 3 個(gè) axios 類型定義就行了 // 另外我們需要定義下自己的攔截器 和 請(qǐng)求結(jié)果封裝
代碼也不多,就也不多解釋了,基本注釋都加上了。下面是全部代碼。
import axios from 'axios' import type { AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios' // 定義一個(gè)常見后端請(qǐng)求返回 type BaseApiResponse<T> = { code: number message: string result: T } // 拓展 axios 請(qǐng)求配置,加入我們自己的配置 interface RequestOptions { // 是否全局展示請(qǐng)求 錯(cuò)誤信息 globalErrorMessage?: boolean // 是否全局展示請(qǐng)求 成功信息 globalSuccessMessage?: boolean } // 拓展自定義請(qǐng)求配置 interface ExpandAxiosRequestConfig<D = any> extends AxiosRequestConfig<D> { interceptorHooks?: InterceptorHooks requestOptions?: RequestOptions } // 拓展 axios 請(qǐng)求配置 interface ExpandInternalAxiosRequestConfig<D = any> extends InternalAxiosRequestConfig<D> { interceptorHooks?: InterceptorHooks requestOptions?: RequestOptions } // 拓展 axios 返回配置 interface ExpandAxiosResponse<T = any, D = any> extends AxiosResponse<T, D> { config: ExpandInternalAxiosRequestConfig<D> } export interface InterceptorHooks { requestInterceptor?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig requestInterceptorCatch?: (error: any) => any responseInterceptor?: (response: AxiosResponse) => AxiosResponse | Promise<AxiosResponse> responseInterceptorCatch?: (error: any) => any } // 導(dǎo)出Request類,可以用來自定義傳遞配置來創(chuàng)建實(shí)例 export default class Request { // axios 實(shí)例 private _instance: AxiosInstance // 默認(rèn)配置 private _defaultConfig: ExpandAxiosRequestConfig = { baseURL: '/api', timeout: 5000, requestOptions: { globalErrorMessage: true, globalSuccessMessage: false } } private _interceptorHooks?: InterceptorHooks constructor(config: ExpandAxiosRequestConfig) { // 使用axios.create創(chuàng)建axios實(shí)例 this._instance = axios.create(Object.assign(this._defaultConfig, config)) this._interceptorHooks = config.interceptorHooks this.setupInterceptors() } // 通用攔截,在初始化時(shí)就進(jìn)行注冊(cè)和運(yùn)行,對(duì)基礎(chǔ)屬性進(jìn)行處理 private setupInterceptors() { this._instance.interceptors.request.use(this._interceptorHooks?.requestInterceptor, this._interceptorHooks?.requestInterceptorCatch) this._instance.interceptors.response.use(this._interceptorHooks?.responseInterceptor, this._interceptorHooks?.responseInterceptorCatch) } // 定義核心請(qǐng)求 public request(config: ExpandAxiosRequestConfig): Promise<AxiosResponse> { // !??!?? 注意:axios 已經(jīng)將請(qǐng)求使用 promise 封裝過了 // 這里直接返回,不需要我們?cè)偈褂?nbsp;promise 封裝一層 return this._instance.request(config) } public get<T = any>(url: string, config?: ExpandAxiosRequestConfig): Promise<AxiosResponse<BaseApiResponse<T>>> { return this._instance.get(url, config) } public post<T = any>(url: string, data?: any, config?: ExpandAxiosRequestConfig): Promise<T> { return this._instance.post(url, data, config) } public put<T = any>(url: string, data?: any, config?: ExpandAxiosRequestConfig): Promise<T> { return this._instance.put(url, data, config) } public delete<T = any>(url: string, config?: ExpandAxiosRequestConfig): Promise<T> { return this._instance.delete(url, config) } }
以及使用的 demo
。這個(gè)保姆級(jí)服務(wù)滿意嗎?
// 請(qǐng)求攔截器 const transform: InterceptorHooks = { requestInterceptor(config) { // 請(qǐng)求頭部處理,如添加 token const token = 'token-value' if (token) { config!.headers!.Authorization = token } return config }, requestInterceptorCatch(err) { // 請(qǐng)求錯(cuò)誤,這里可以用全局提示框進(jìn)行提示 return Promise.reject(err) }, responseInterceptor(result) { // 因?yàn)?nbsp;axios 返回不支持?jǐn)U展自定義配置,需要自己斷言一下 const res = result as ExpandAxiosResponse // 與后端約定的請(qǐng)求成功碼 const SUCCESS_CODE = 1 if (res.status !== 200) return Promise.reject(res) if (res.data.code !== SUCCESS_CODE) { if (res.config.requestOptions?.globalErrorMessage) { // 這里全局提示錯(cuò)誤 console.error(res.data.message) } return Promise.reject(res.data) } if (res.config.requestOptions?.globalSuccessMessage) { // 這里全局提示請(qǐng)求成功 console.log(res.data.message) } // 請(qǐng)求返回值,建議將 返回值 進(jìn)行解構(gòu) return res.data.result }, responseInterceptorCatch(err) { // 這里用來處理 http 常見錯(cuò)誤,進(jìn)行全局提示 const mapErrorStatus = new Map([ [400, '請(qǐng)求方式錯(cuò)誤'], [401, '請(qǐng)重新登錄'], [403, '拒絕訪問'], [404, '請(qǐng)求地址有誤'], [500, '服務(wù)器出錯(cuò)'] ]) const message = mapErrorStatus.get(err.response.status) || '請(qǐng)求出錯(cuò),請(qǐng)稍后再試' // 此處全局報(bào)錯(cuò) console.error(message) return Promise.reject(err.response) } } // 具體使用時(shí)先實(shí)例一個(gè)請(qǐng)求對(duì)象 const request = new Request({ baseURL: '/api', timeout: 5000, interceptorHooks: transform }) // 定義請(qǐng)求返回 interface ResModel { str: string num: number } // 發(fā)起請(qǐng)求 request .post<ResModel>( '/abc', { a: 'aa', b: 'bb' }, { requestOptions: { globalErrorMessage: true } } ) .then((res) => { console.log('res: ', res) console.log(res.str) })
可以看到鼠標(biāo)浮上去就能看到定義了,完美!
到此,相信大家對(duì)“ts如何封裝axios”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。