這篇文章沒甚麼特別的,只是純粹應用了一次axios
的錯誤處理而已,希望表達在應用程式內,將重複程式碼抽象出來利用的範例
基本語法範例
axios
與 jquery
語法都還蠻像的,經由config
設定發出請求的網址、資料,像是下面這樣
1 2 3 4 5 6 7 8
| axios({ method: 'post', url: '/user/12345', data: { firstName: 'bar', lastName: 'foo', }, });
|
也可以經由別名來處理網址、資料,若是需要也可以再添加config
1 2 3 4 5 6 7 8 9 10
| axios.post( '/user/12345', { firstName: 'bar', lastName: 'foo', }, { } );
|
官網已經寫得很清楚了,細節就請移步官網瀏覽
情境
當我們的程式碼越來越多、也越來越複雜的時候,為了維護方便,我們可能會自然而然地將架構逐漸演化,假設是一個登陸頁面好了,除了基本的頁面進入點index.js
,可能還會在裡面有一個Service
來處理這個頁面的一些操作,因為Service
只是負責處理邏輯,一些比較細節的處理則是再放給Helper
、Utiliy
、Adapter
之類的去做,而為了便於維護,我也會使用AxiosHelper
去將一些行為包裝起來,所以輸入帳號密碼登入的操作會是像這樣
1 2 3 4 5
| <form> Name:<input type="text" name="name" id="name" v-model="form.name" /> Pass:<input type="text" name="pass" id="pass" v-model="form.pass" /> <button v-on:click="loginHandler">Login</button> </form>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
new Vue({ data() { return { form: { name: '', pass: '', }, }; }, methods: { async loginHandler() { sweetAlertHelper.ShowLoading(); let { isSuccess, message } = await memberService.login({ ...this.form }); sweetAlertHelper.CloseModal(); if (isSuccess) { window.location.href = '/Member'; } else { logService.loginFailed({ ...this.form }, message); sweetAlertHelper.showError(message); } }, }, });
|
1 2 3 4 5 6 7 8
| import MemberAdapter from './MemberAdapter.js'; const MemberService = { login({ name, pass }) { return MemberAdapter.login({ name, pass }); }, }; export default MemberService;
|
1 2 3 4 5 6 7 8
| import AxiosHelper from './AxiosHelper.js' import MemberAdapter = { login({name,pass}){ return AxiosHelper.sendRequest('/Login',{name,pass}) } } export default MemberAdapter;
|
1 2 3 4 5 6 7 8
| import axios from 'axios'; const AxiosHelper = { sendRequest: async (url, sendData) => { return (await axios.post(url, sendData)).data; }, }; export default AxiosHelper;
|
按照上面的程式碼來看,登入的回應如果是正確或失敗,都是有動作的,乍看之下沒甚麼問題,但是如果後端伺服器沒有回應呢?最常見的就是後端很忙,結果前端請求就一直掛在那邊變成 timeout,然後因為程式碼在呼叫後端之前,透過SweetAlertHelper
將畫面墊了一層遮罩,秀出 Loading 畫面,避免讓使用者重複送出請求,結果因為後端 Timeout,則前端 Js 就掛掉了,於是使用者看到的畫面就是一直轉圈圈的 Loading 畫面
上面程式碼沒有實際跑過,只是為了讓大家比較理解情境隨手寫的,跑不起來的
解決方案
既然我們針對的情境是要解決 timeout
,那我們就直接使用官方所提供的錯誤處理不就好了?
是的,沒有錯,我們就直接套用就行了,OK,結案。
因為我們已經將所有使用到 axios
的東西都封裝在 AxiosHelper
裡面了,所以我們也只需要改一個地方就好了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import axios from 'axios'; const AxiosHelper = { sendRequest: async (url, sendData) => { try { return (await axios.post(url, sendData, { timeout: 5000 })).data; } catch (error) { sweetAlertHelper.showError('伺服器忙碌,請稍後再試'); throw error; } }, };
|
這樣子的話,在原先程式碼的部分,就不會繼續往下執行,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| async loginHandler(){ sweetAlertHelper.ShowLoading() let {isSuccess, message} = await memberService.login({...this.form})
}
|
原本的程式碼就會再呼叫完畢後,拋出例外,直接中斷掉,使用者也能看到畫面顯示伺服器忙碌
,同時我們也只需要改一個地方,其他頁面都不需再調整,好吧,技術本身沒甚麼難度,但是共用的抽象出來才是我要表達的
延伸議題
#研發解決方案#易車前端監控系統:這篇文章是某一天我逛到的,它們自己做了一套監控系統,在錯誤處理的部分,也可以將這些資訊像它們一樣,不管是透過自己建立,或者是用現有 Open Source 解決方案,都是不錯的,不過我沒有再研究下去,有興趣的朋友可以點進去看看
使用 Axios 你的 API 都怎麼管理:這篇則是一位知名的前端 Youtuber 寫的一篇關於 axios
的東西,概念上是不錯的,他這篇文章主要針對的情境是你可能服務來自好幾個Domain
所以會需要這樣做,但我碰到的情境這部分會在後端就整合起來而不是在前端來做。所以他的辦法就比較不合我用,但是概念上都是為了便於管理,也是一個不錯的案例解決方案,提供大家參考
這也是為什麼我會說要看情況套用解決方案,別人的best practice
不一定適合你,多看多參考,你會有自己的想法的