摘要:本著懶的原則,需要對(duì)接口錯(cuò)誤進(jìn)行統(tǒng)一處理。方案業(yè)務(wù)代碼直接使用,頂?shù)艚y(tǒng)一的錯(cuò)誤信息。稍作抽象與封裝就可以形成一個(gè)業(yè)務(wù)無(wú)關(guān)框架無(wú)關(guān)的統(tǒng)一錯(cuò)誤處理方案。
問(wèn)題
在進(jìn)行業(yè)務(wù)開(kāi)發(fā)的時(shí)候,前后端會(huì)對(duì)接口的數(shù)據(jù)結(jié)構(gòu)進(jìn)行約定,若接口有異常,需要將異常信息展示給用戶知曉。這個(gè)流程里,數(shù)據(jù)結(jié)構(gòu)是確定的(事先約定),數(shù)據(jù)的處理邏輯是相同的(展示給用戶),如果在業(yè)務(wù)代碼代碼中重復(fù)的catch(e) { 展示給用戶 },就非常的不優(yōu)雅。本著Don"t repeat myself(懶)的原則,需要對(duì)接口錯(cuò)誤進(jìn)行統(tǒng)一處理。
接下來(lái),我會(huì)結(jié)合具體的業(yè)務(wù)場(chǎng)景,講一講我的解決方案。
后端通過(guò)http狀態(tài)標(biāo)識(shí)接口狀態(tài),錯(cuò)誤信息在response的data里
前端的處理邏輯是使用element-ui的Message展示錯(cuò)誤信息
使用axios
axios可以通過(guò)攔截器,在業(yè)務(wù)代碼處理響應(yīng)之前對(duì)響應(yīng)進(jìn)行處理,類似于下面的流程
someAPI() .then(interceptorsFn) .then(業(yè)務(wù)邏輯)
所以,我們可以在interceptors對(duì)響應(yīng)進(jìn)行統(tǒng)一處理:
request.interceptors.response.use( (response) => response.data, (error) => { // 針對(duì)特定的http狀態(tài)碼進(jìn)行處理 if (error.response && error.response.status === 401) { router.push({ name: "ssoLogin" }) return new Promise(() => {}) // pending的promise,中止promise鏈 } ..... const msg = error.response.data Message.error(msg) return Promise.reject(error.response) } )如何進(jìn)行特定的錯(cuò)誤處理
不難看出,上面的方案有一個(gè)問(wèn)題,如果有某個(gè)接口需要有業(yè)務(wù)代碼來(lái)展示定制的錯(cuò)誤信息(這個(gè)情況十分常見(jiàn)),如何處理?
naive方案1:業(yè)務(wù)代碼使用其它的方式展示信息:例如Notify。這個(gè)方案被我司產(chǎn)品痛罵,因?yàn)槠茐牧私y(tǒng)一的錯(cuò)誤信息展示,并且此時(shí)統(tǒng)一的錯(cuò)誤信息是一個(gè)垃圾信息,沒(méi)必要展示。
naive方案2:業(yè)務(wù)代碼直接使用Message,頂?shù)艚y(tǒng)一的錯(cuò)誤信息。這個(gè)方案還是被產(chǎn)品大哥(dog)懟了,因?yàn)槊黠@的用戶體驗(yàn)不好,錯(cuò)誤信息出現(xiàn)了閃爍。
帥氣的解決方案3:業(yè)務(wù)代碼決定是否隱藏統(tǒng)一錯(cuò)誤提示那么問(wèn)題來(lái)了,由于是先走攔截器,再走業(yè)務(wù)代碼,如何由業(yè)務(wù)代碼決定是否隱藏統(tǒng)一錯(cuò)誤提示呢?
我的辦法是,將統(tǒng)一的錯(cuò)誤提示使用setTimeout放到下一個(gè)loop執(zhí)行,并通過(guò)一個(gè)變量標(biāo)識(shí)是否要執(zhí)行統(tǒng)一錯(cuò)誤提示。
request.interceptors.response.use( (response) => response.data, (error) => { ... setTimeout(() => { if (tag) { Message.error(msg) } }) } )
接下來(lái),需要考慮的是,如何在業(yè)務(wù)代碼里改變標(biāo)識(shí)變量
naive方案1:一個(gè)全局的變量或者方法這個(gè)方案非常的不靠譜,若在其它代碼里改變了這個(gè)全局變量,就嗝屁,并且N個(gè)接口公用一個(gè)標(biāo)識(shí)變量,只能是同一個(gè)狀態(tài)。
帥氣方案2:request.interceptors.response.use( (response) => response.data, (error) => { ... let isShowNormalError = true const hideNormalError = () => isShowNormalError = false setTimeout(() => { if (isShowNormalError) { Message.error(msg) } }) return Promise.reject({ ...error.response, hideNormalMessage }) // 在error.response上添加方法 } )
業(yè)務(wù)代碼:
someAPIFN() .then() .catch({ data, hideNormalMessage }) { // 業(yè)務(wù)代碼 hideNormalMessage() }兼容舊代碼
目前的方案需要對(duì)現(xiàn)存代碼做修改,對(duì)進(jìn)行特殊處理的接口添加hideNormalMessage()。如果不想全局搜索添加代碼(懶),可以根據(jù)業(yè)務(wù)來(lái)進(jìn)行兼容。下面講一下我結(jié)合業(yè)務(wù)代碼進(jìn)行的兼容處理(非常不推薦)。
request.interceptors.response.use( (response) => response.data, (error) => { // warning,和業(yè)務(wù)代碼深度耦合,不推薦 const hasMessageBeforeCatch = !!document.querySelector(".el-message") ... let isShowNormalError = true const hideNormalError = () => isShowNormalError = false setTimeout(() => { const hasMessageAfterCatch = document.querySelector(".el-message") // 調(diào)用catch前沒(méi)有message,調(diào)用catch后有message,表示message是在catch過(guò)程中產(chǎn)生 const madeMessageWhenCatch = !hasMessageBeforeCatch && hasMessageAfterCatch if (isShowNormalError && !madeMessageWhenCatch) { Message.error(msg) } }) return Promise.reject({ ...error.response, hideNormalMessage }) // 在error.response上添加方法 } )
邏輯:如果在catch中使用了Message,就不展示統(tǒng)一錯(cuò)誤處理
總結(jié)這個(gè)解決方案的關(guān)鍵在于使用setTimeout使得統(tǒng)一錯(cuò)誤處理“落后”于業(yè)務(wù)代碼,并在Promise.reject的參數(shù)中添加控制函數(shù)使得業(yè)務(wù)代碼可以決定是否展示統(tǒng)一錯(cuò)誤處理。稍作抽象與封裝就可以形成一個(gè)業(yè)務(wù)無(wú)關(guān)、框架無(wú)關(guān)的統(tǒng)一錯(cuò)誤處理方案。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/97977.html
摘要:今天松哥就帶大家來(lái)看看的使用。此時(shí)啟動(dòng)前端項(xiàng)目,就可以順利發(fā)送網(wǎng)絡(luò)請(qǐng)求了。松哥將自己封裝的網(wǎng)絡(luò)請(qǐng)求庫(kù)已經(jīng)放在上,歡迎大家參考。前端網(wǎng)絡(luò)訪問(wèn),主流方案就是 Ajax,Vue 也不例外,在 Vue2.0 之前,網(wǎng)絡(luò)訪問(wèn)較多的采用 vue-resources,Vue2.0 之后,官方不再建議使用 vue-resources ,這個(gè)項(xiàng)目本身也停止維護(hù),目前建議使用的方案是 axios。今天松哥就帶大...
摘要:攔截重復(fù)請(qǐng)求如何標(biāo)識(shí)每個(gè)請(qǐng)求下面函數(shù),通過(guò)一個(gè)請(qǐng)求參數(shù)中的請(qǐng)求傳遞參數(shù)或請(qǐng)求傳遞參數(shù)來(lái)表示每一個(gè)請(qǐng)求。 一直想封裝一下 axios, 可以方便項(xiàng)目中使用,今天有時(shí)間,就好好研究了一下。 源碼: // util/axios.js import axios from axios const pending = {} const CancelToken = axios.CancelTok...
摘要:請(qǐng)求和返回?cái)?shù)據(jù)攔截,統(tǒng)一請(qǐng)求報(bào)錯(cuò)提示官方文檔英文文檔中文文檔請(qǐng)求和返回?cái)r截,添加統(tǒng)一的報(bào)錯(cuò)信息請(qǐng)求的配置可以通過(guò)閱讀官方文檔來(lái)進(jìn)行配置。寫(xiě)好之后,在寫(xiě)發(fā)送請(qǐng)求的文件中引用就可以了。攔截所有有請(qǐng)求與回復(fù)請(qǐng)求錯(cuò)誤,請(qǐng)重試請(qǐng)求錯(cuò)誤,請(qǐng)重試 axios請(qǐng)求、和返回?cái)?shù)據(jù)攔截,統(tǒng)一請(qǐng)求報(bào)錯(cuò)提示 官方文檔 https://github.com/axios/axios 英文文檔 https://w...
摘要:使用了攔截器處理相關(guān)問(wèn)題,這樣就不再需要使用來(lái)做錯(cuò)誤的處理。萬(wàn)惡的攔截器一些處理無(wú)論是對(duì)成功的處理還是對(duì)失敗的處理,如果攔截器不拋出錯(cuò)誤,那么終將還會(huì)執(zhí)行里面處理請(qǐng)求成功的函數(shù),即使你返回。 一 前言 本文適合剛接觸axios或者使用過(guò)幾次的同學(xué)來(lái)分享交流一些入門經(jīng)驗(yàn),本文同樣適用熟悉axios的同學(xué)來(lái)作為參考手冊(cè)。默認(rèn)你已經(jīng)看過(guò)axios的相關(guān)文檔:axios文檔 GitHub,通過(guò)...
摘要:如果用戶已經(jīng)登錄,則順利進(jìn)入路由,否則就進(jìn)入登錄頁(yè)面。如果全部鉤子執(zhí)行完了,則導(dǎo)航的狀態(tài)就是確認(rèn)的。通過(guò)這個(gè)字段來(lái)判斷該路由是否需要登錄權(quán)限。還有一種情況便是當(dāng)前失效了,但是依然保存在本地。通過(guò)配置,當(dāng)后端接口返回未授權(quán),讓用戶重新登錄。 vue+axios 前端實(shí)現(xiàn)登錄攔截(路由攔截、http攔截) 一、路由攔截登錄攔截邏輯第一步:路由攔截首先在定義路由的時(shí)候就需要多添加一個(gè)自定義字...
閱讀 1291·2021-11-25 09:43
閱讀 1654·2021-10-25 09:47
閱讀 2525·2019-08-30 13:46
閱讀 811·2019-08-29 13:45
閱讀 1337·2019-08-26 13:29
閱讀 3059·2019-08-23 15:30
閱讀 1169·2019-08-23 14:17
閱讀 1373·2019-08-23 13:43