舉個(gè)栗子耐床,如果用戶在沒有登陸的條件下調(diào)用接口肥荔,那么所有接口都應(yīng)該返回一個(gè)狀態(tài)碼表示用戶沒有登陸憋肖,此時(shí)需要跳轉(zhuǎn)到登陸頁進(jìn)行登陸掉瞳。
但是如果每次調(diào)用接口都需要判斷一下,代碼就會顯得十分冗余它抱,因此我們定義了一個(gè)apAjax.js秕豫,核心代碼如下:
const apAjax = (options) => {
// 一些配置代碼
return new Promise((resolve, reject) => {
axios({
method: options.method,
url: options.url,
data: options.data,
...
}).then((res) => {
resolve(res)
if(res.code == 401) {
// 跳轉(zhuǎn)到登陸頁
}
// 其他代碼
}).catch((error) => {
reject(error)
})
})
}
調(diào)用
import apAjax from 'apAjax.js'
apAjax(options).then(res => {
// 在這里我們只需要處理接口正常返回的情況即可
// 因?yàn)槲吹顷懙那闆r已經(jīng)在apAjax.js里面統(tǒng)一處理了
})
看上去代碼更加精簡了,并且在全局有了統(tǒng)一的錯(cuò)誤處理观蓄,但是當(dāng)我們的項(xiàng)目接入sentry日志監(jiān)控之后混移,卻收到了下圖的報(bào)錯(cuò)信息
明明在封裝的apAjax函數(shù)里面進(jìn)行了catch錯(cuò)誤捕獲,為什么還會報(bào)錯(cuò)呢蜘腌?
可以看到我們axios函數(shù)的then方法里面第一行代碼就是resolve(res)
沫屡,這時(shí)候Promise的狀態(tài)已經(jīng)變成了resolved
,這種改變是不可逆的撮珠,此時(shí)就算后面的其他代碼拋出異常沮脖,也不會被catch方法捕獲到金矛。
另外,Promise對象的錯(cuò)誤還有“冒泡”的性質(zhì)勺届,會一直向后傳遞驶俊,直到被捕獲為止。但是上面的調(diào)用代碼只有then
沒有catch
免姿。(以為被全局統(tǒng)一捕獲了饼酿,所以沒寫)最終誕生了這個(gè)無家可歸的異常。
不僅如此, Promise之間涇渭分明胚膊,內(nèi)部Promise拋出的任何錯(cuò)誤故俐,外部Promise對象都無法感知并捕獲。 同時(shí)紊婉,由于promise是異步的药版,try catch語句也無法捕獲其錯(cuò)誤。
因此養(yǎng)成良好習(xí)慣喻犁,不要偷懶槽片,每一個(gè)Promise都請記得寫上catch。