重慶網(wǎng)站租賃空間國內(nèi)新聞最新消息今天
大廠技術(shù)??高級前端??Node進階
點擊上方?程序員成長指北,關(guān)注公眾號
回復(fù)1,加入高級Node交
前言 寫異步函數(shù)的時候,promise 和 async 兩種方案都非常常見,甚至同一個項目里,不同的開發(fā)人員都使用不同的習(xí)慣, 不過關(guān)于兩者的比較不是本文關(guān)注的重點,只總結(jié)為一句話:“async 是異步編程的終極解決方案”。
當(dāng)使用 async 函數(shù)的時候,很多文章都說建議用?try catch
?來捕獲異常, 可是實際上我看了很多項目的代碼,遵循的并不是嚴謹,很多都沒有用,甚至 catch 函數(shù)都沒寫,這是為什么呢?
我們先看下使用 try catch 情況下的代碼示例:
示例1 :使用 try catch
function?getUserInfo?()?{return?new?Promise((resolve,?reject)?=>?{setTimeout(()?=>?{reject('請求異常')},?1000)})
}async?function?logined?()?{try?{let?userInfo?=?await?getUserInfo()//?執(zhí)行中斷l(xiāng)et?pageInfo?=?await?getPageInfo(userInfo?.userId)}?catch(e)?{console.warn(e)}
}logined()
復(fù)制代碼
執(zhí)行后會在 catch 里捕獲?請求異常
,然后 getUserInfo 函數(shù)中斷執(zhí)行,這是符合邏輯的,對于有依賴關(guān)系的接口,中斷執(zhí)行可以避免程序崩潰,這里唯一的問題是 try catch 貌似占據(jù)了太多行數(shù),如果每個接口都寫的話看起來略顯冗余。
示例2:直接 catch
鑒于正常情況下,await
?命令后面是一個 Promise 對象, 所以上面代碼可以很自然的想到優(yōu)化方案:
function?getUserInfo?()?{return?new?Promise((resolve,?reject)?=>?{setTimeout(()?=>?{reject('請求異常')},?1000)})
}async?function?logined?()?{let?userInfo?=?await?getUserInfo().catch(e?=>?console.warn(e))//?執(zhí)行沒有中斷,userInfo?為?undefinedif?(!userInfo)?return?//?需要做非空校驗let?pageInfo?=?await?getPageInfo(userInfo?.userId)
}logined()
復(fù)制代碼
執(zhí)行后 catch 可以正常捕獲異常,但是程序沒有中斷,返回值?userInfo
?為?undefined
, 所以如果這樣寫的話,就需要對返回值進行非空校驗,?if (!userInfo) return
?我覺得這樣有點反邏輯,異常時就應(yīng)該中斷執(zhí)行才對;
示例3:在 catch 里 reject
可以繼續(xù)優(yōu)化,在 catch 里面加一行?return Promise.reject(e)
, 可以使 await 中斷執(zhí)行;
完整代碼:
function?getUserInfo?()?{return?new?Promise((resolve,?reject)?=>?{setTimeout(()?=>?{reject('請求異常')},?1000)})
}async?function?logined?()?{let?userInfo?=?await?getUserInfo().catch(e?=>?{console.warn(e)return?Promise.reject(e)?//?會導(dǎo)致控制臺出現(xiàn)?uncaught?(in?promise)?報錯信息})//?執(zhí)行中斷l(xiāng)et?pageInfo?=?await?getPageInfo(userInfo?.userId)
}logined()
復(fù)制代碼
一般我們在項目里都是用 axios 或者 fetch 之類發(fā)送請求,會對其進行一個封裝,也可以在里面進行 catch 操作,對錯誤信息先一步處理,至于是否需要 reject,就看你是否想要在 await 命令異常時候中斷了;不使用 reject 則不會中斷,但是需要每個接口拿到 response 后先 非空校驗, 使用 reject 則會在異常處中斷,并且會在控制臺暴露?uncaught (in promise)
?報錯信息。

建議
不需要在 await 處異常時中斷,可以這樣寫,需要做非空校驗,控制臺不會有報錯信息
let?userInfo?=?await?getUserInfo().catch(e?=>?console.warn(e))
if?(!userInfo)?return
復(fù)制代碼
需要在 await 處異常時中斷,并且在意控制臺報錯,可以這樣寫
try?{let?userInfo?=?await?getUserInfo()//?執(zhí)行中斷l(xiāng)et?pageInfo?=?await?getPageInfo(userInfo?.userId)
}?catch(e)?{console.warn(e)
}復(fù)制代碼
需要在 await 處異常時中斷,但是不在意控制臺報錯,則可以這樣寫
let?userInfo?=?await?getUserInfo().catch(e?=>?{console.warn(e)return?Promise.reject(e)?//?會導(dǎo)致控制臺出現(xiàn)?uncaught?(in?promise)?報錯信息
})
//?執(zhí)行中斷
let?pageInfo?=?await?getPageInfo(userInfo?.userId)復(fù)制代碼
小結(jié)
幾種寫法,初看可能覺得第三種 catch 這種寫法是最好的,但是細想下,從用戶體驗上來看,我覺得 try catch 是最好的,邏輯直觀、符合同步編程思維,控制臺不會暴露?uncaught (in promise)
?報錯信息;
而鏈?zhǔn)秸{(diào)用的 catch (里面再 reject),是傳統(tǒng) promise 的回調(diào)寫法,既然已經(jīng)用 async await 這種同步編程寫法了,再用 catch 鏈?zhǔn)綄懛?#xff0c;感覺沒必要。
結(jié)語
我是考拉🐨,一個熱心的前端菜鳥程序員。如果你上進,喜歡前端,想學(xué)習(xí)前端,那咱們可以交朋友,一起摸魚哈哈,摸魚群,關(guān)注我,拉你進群,有5000多名前端小伙伴在等著一起學(xué)習(xí)哦 -->
作者:Ethan_Zhou
鏈接:https://juejin.cn/post/7213362932423376933
來源:稀土掘金
Node 社群
我組建了一個氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對Node.js學(xué)習(xí)感興趣的話(后續(xù)有計劃也可以),我們可以一起進行Node.js相關(guān)的交流、學(xué)習(xí)、共建。下方加 考拉 好友回復(fù)「Node」即可。
“分享、點贊、在看” 支持一波👍