await/async無法捕獲與處理錯(cuò)誤信息的解決方案分享
前言
如果你對同步任務(wù)/異步任務(wù)/回到地獄/promise概念/async-await的作用不是很了解的話,或許需要看一下以下簡單的介紹。
如果都了解則可以直接點(diǎn)擊側(cè)邊欄跳到下面看await無法處理錯(cuò)誤信息的解決方案。
同步和異步
javascript是一個(gè)單線程的語言。因?yàn)槭菃尉€程。所以這直接導(dǎo)致了線程阻塞的問題,在前一個(gè)任務(wù)完成以前,后面所有的任務(wù)都無法執(zhí)行。因?yàn)檫@個(gè)問題。所以javascript有了異步任務(wù)的概念。
javascript把其中的任務(wù)分為兩部分,一種是同步任務(wù),一種是異步任務(wù),一些可能造成阻塞的任務(wù)歸為異步任務(wù),并將異步任務(wù)放到所有的同步任務(wù)之后去執(zhí)行,以解決阻塞問題。
常見的異步任務(wù)有
- settimeout/setInterval
- Promise的then函數(shù)
- XMLHttpRequest(http請求也就是ajax)
異步任務(wù)解決了執(zhí)行堵塞的問題,同時(shí)也存在一些問題(如下)。
異步任務(wù)所存在的問題
異步任務(wù)需要回調(diào)來處理任務(wù)結(jié)束以后的一些動作。在一些特殊場景下,有些異步任務(wù)需要依賴于其他異步任務(wù)的回調(diào)。這就需要將需要依賴的異步任務(wù)寫到被依賴的異步任務(wù)的回調(diào)中。
這是一種解決依賴異步依賴的方案,雖然可行,但不可讀。 總會出現(xiàn)依賴層級較多的情況,大量的層級會讓這個(gè)功能變得非?;逎???勺x性極差。如下??
雖然一般開發(fā)中很少會出現(xiàn)這種嵌套7層的異步任務(wù)。但嵌套3,4層還是相對常見的。多層的嵌套配合本身存在的邏輯。對代碼的閱讀非常不友好。前端工程師們?yōu)榱私鉀Q這個(gè)問題。在ES6中推出了Promise。
Promise如何解決回調(diào)地獄
Promise提供resolve和reject兩個(gè)函數(shù)來代表異步任務(wù)的成功和失敗。最關(guān)鍵的一點(diǎn)是Promise提供了.then()和.catch()函數(shù),.then()函數(shù)負(fù)責(zé)處理異步任務(wù)成功后的動作,.catch()負(fù)責(zé)處理異步任務(wù)失敗后的動作。
他們在一定程度上優(yōu)化了回調(diào)地獄
Promise還可以進(jìn)行鏈?zhǔn)秸{(diào)用
雖然Promise對于地獄回調(diào)有所改善。但他依然有著一定的嵌套結(jié)構(gòu)存在。有沒有什么方案可以徹底脫離嵌套結(jié)構(gòu)?
有
es6后來又推出了async/await(Promise的語法糖)。
async/await,回調(diào)地獄的最終方案
async/await完全解決了回調(diào)嵌套的問題。實(shí)現(xiàn)了以看似同步的代碼,完成異步的需求。
async右邊的函數(shù)會返回一個(gè)Promise對象。如圖??
await是等待一個(gè)async函數(shù)執(zhí)行完畢,并提取Promise中的值。??
這樣,我們就擺脫了嵌套結(jié)構(gòu)的問題?,F(xiàn)在我們來看下整套一起使用。
async/await錯(cuò)誤處理方案
async/await作為promise的語法糖。它徹底解決了回調(diào)地獄的問題,但也存在一個(gè)問題。相對于Promise的鏈?zhǔn)秸{(diào)用。async/await無法捕獲錯(cuò)誤。普通的Promise是通過.catch()和reject()配合來進(jìn)行錯(cuò)誤程序處理。但是async/await并沒有在語法內(nèi)部提供錯(cuò)誤處理。
這就導(dǎo)致了如果異步請求錯(cuò)誤,我們無法做出相應(yīng)補(bǔ)救措施而且錯(cuò)誤信息會在控制臺打印。
現(xiàn)在我們常規(guī)await的處理方案有以下幾種。
第一種,手動添加啊try{}catch{}進(jìn)行捕獲
我們可以通過手動給async函數(shù)內(nèi)部添加*try{}catch{}*來進(jìn)行錯(cuò)誤捕獲,如此,就可以避免錯(cuò)誤在控制臺打印和阻塞代碼的運(yùn)行。如下
這種做法的弊端是:需要捕獲錯(cuò)誤的async多的話。每一個(gè)都寫下去,就比較麻煩和不可讀了。
第二種,使用await-to-js庫
網(wǎng)上總有大牛幫我們解決這些問題。await-to-js是一個(gè)幫助我們解決異步錯(cuò)誤處理的庫,知名度較高,到目前有2.7k的?。
import to from "await-to-js"; //模擬請求 const handleFetch = async () => { fetch("/url",{}) } //進(jìn)行錯(cuò)誤捕獲和處理 const [err, result] = await to(handleFetch()); if (err) { //進(jìn)行錯(cuò)誤動作處理 }
這是一種比較簡單的處理方式
源碼 ---ts版本
| --- | ------------------------------------------------------------------------------------- | | | * @param { Promise } promise | | | * @param { Object= } errorExt - Additional Information you can pass to the err object | | | * @return { Promise } | | | */ | | | export function to<T, U = Error> ( | | | promise: Promise<T>, | | | errorExt?: object | | | ): Promise<[U, undefined] | [null, T]> { | | | return promise | | | .then<[null, T]>((data: T) => [null, data]) | | | .catch<[U, undefined]>((err: U) => { | | | if (errorExt) { | | | const parsedError = Object.assign({}, err, errorExt); | | | return [parsedError, undefined]; | | | } | | | | | | return [err, undefined]; | | | }); | | | } | | | | | | export default to
ts版本的源碼可能不便于閱讀,以下是我翻譯成js版本的源碼 ,并附加注解
export function to( promise, errorExt, ) { return promise //成功,則error返回null,result返回data .then((data) => [null, data]) //錯(cuò)誤則捕獲錯(cuò)誤內(nèi)容,然后返回錯(cuò)誤信息,result為undefined .catch((err) => { if (errorExt) { const parsedError = Object.assign({}, err, errorExt); return [parsedError, undefined]; } return [err, undefined]; }); }
最后
相較于自己使用try和catch進(jìn)行捕獲,我更喜歡使用await-to-js這個(gè)庫,簡單方便,而且貼近hooks的寫法讓我覺得親切。
是否有必要給每一個(gè)請求都加上一個(gè)錯(cuò)誤捕獲?我想是不需要的。我們需要知道,錯(cuò)誤捕獲并不是無償?shù)?。在很多情況下我們并不需要去做這種特殊的處理,比如獲取分頁數(shù)據(jù)等。一般情況,只需要給一些可能會出現(xiàn)問題的async/await做這個(gè)處理即可。
總結(jié)
捕獲async和await的方法有兩種
- 手動添加try{}catch{}
- 使用await-to-js異步錯(cuò)誤處理庫
到此這篇關(guān)于await/async無法捕獲與處理錯(cuò)誤信息的解決方案的文章就介紹到這了,更多相關(guān)await/async無法捕獲與處理錯(cuò)誤內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js超時(shí)調(diào)用setTimeout和間歇調(diào)用setInterval實(shí)例分析
這篇文章主要介紹了js超時(shí)調(diào)用setTimeout和間歇調(diào)用setInterval,以實(shí)例形式對比分析了setTimeout與setInterval的具體使用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-01-01input file上傳 圖片預(yù)覽功能實(shí)例代碼
input file上傳圖片預(yù)覽其實(shí)很簡單。今天小編就通過本文給大家介紹input file上傳 圖片預(yù)覽功能的實(shí)現(xiàn)代碼,比較簡單,對input file 上傳預(yù)覽功能感興趣的朋友參考下吧2016-10-10JavaScript簡單獲取系統(tǒng)當(dāng)前時(shí)間完整示例
這篇文章主要介紹了JavaScript簡單獲取系統(tǒng)當(dāng)前時(shí)間的方法,涉及javascript針對日期與時(shí)間的判斷以及字符串組合的相關(guān)技巧,需要的朋友可以參考下2016-08-08超鏈接怎么正確調(diào)用javascript函數(shù)
本文介紹使用超鏈接調(diào)用javasript函數(shù)且不會影響GIF圖片動畫的方法,有遇到相同問題的小伙伴可以參考一下。2016-05-05JavaScript判斷是否為數(shù)字的幾種方式匯總(推薦!)
有時(shí)候需要根據(jù)輸入的內(nèi)容來進(jìn)行計(jì)算,這個(gè)時(shí)候就需要判斷輸入的內(nèi)容是否是數(shù)字,下面這篇文章主要給大家介紹了關(guān)于JavaScript判斷是否為數(shù)字的幾種方式,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06使用Browserify來實(shí)現(xiàn)CommonJS的瀏覽器加載方法
下面小編就為大家?guī)硪黄褂肂rowserify來實(shí)現(xiàn)CommonJS的瀏覽器加載方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05