await/async無法捕獲與處理錯誤信息的解決方案分享
前言
如果你對同步任務/異步任務/回到地獄/promise概念/async-await的作用不是很了解的話,或許需要看一下以下簡單的介紹。
如果都了解則可以直接點擊側邊欄跳到下面看await無法處理錯誤信息的解決方案。
同步和異步
javascript是一個單線程的語言。因為是單線程。所以這直接導致了線程阻塞的問題,在前一個任務完成以前,后面所有的任務都無法執(zhí)行。因為這個問題。所以javascript有了異步任務的概念。
javascript把其中的任務分為兩部分,一種是同步任務,一種是異步任務,一些可能造成阻塞的任務歸為異步任務,并將異步任務放到所有的同步任務之后去執(zhí)行,以解決阻塞問題。
常見的異步任務有
- settimeout/setInterval
- Promise的then函數(shù)
- XMLHttpRequest(http請求也就是ajax)
異步任務解決了執(zhí)行堵塞的問題,同時也存在一些問題(如下)。
異步任務所存在的問題
異步任務需要回調(diào)來處理任務結束以后的一些動作。在一些特殊場景下,有些異步任務需要依賴于其他異步任務的回調(diào)。這就需要將需要依賴的異步任務寫到被依賴的異步任務的回調(diào)中。
這是一種解決依賴異步依賴的方案,雖然可行,但不可讀。 總會出現(xiàn)依賴層級較多的情況,大量的層級會讓這個功能變得非?;逎?。可讀性極差。如下??

雖然一般開發(fā)中很少會出現(xiàn)這種嵌套7層的異步任務。但嵌套3,4層還是相對常見的。多層的嵌套配合本身存在的邏輯。對代碼的閱讀非常不友好。前端工程師們?yōu)榱私鉀Q這個問題。在ES6中推出了Promise。
Promise如何解決回調(diào)地獄
Promise提供resolve和reject兩個函數(shù)來代表異步任務的成功和失敗。最關鍵的一點是Promise提供了.then()和.catch()函數(shù),.then()函數(shù)負責處理異步任務成功后的動作,.catch()負責處理異步任務失敗后的動作。
他們在一定程度上優(yōu)化了回調(diào)地獄

Promise還可以進行鏈式調(diào)用

雖然Promise對于地獄回調(diào)有所改善。但他依然有著一定的嵌套結構存在。有沒有什么方案可以徹底脫離嵌套結構?
有
es6后來又推出了async/await(Promise的語法糖)。
async/await,回調(diào)地獄的最終方案
async/await完全解決了回調(diào)嵌套的問題。實現(xiàn)了以看似同步的代碼,完成異步的需求。
async右邊的函數(shù)會返回一個Promise對象。如圖??

await是等待一個async函數(shù)執(zhí)行完畢,并提取Promise中的值。??

這樣,我們就擺脫了嵌套結構的問題。現(xiàn)在我們來看下整套一起使用。

async/await錯誤處理方案
async/await作為promise的語法糖。它徹底解決了回調(diào)地獄的問題,但也存在一個問題。相對于Promise的鏈式調(diào)用。async/await無法捕獲錯誤。普通的Promise是通過.catch()和reject()配合來進行錯誤程序處理。但是async/await并沒有在語法內(nèi)部提供錯誤處理。
這就導致了如果異步請求錯誤,我們無法做出相應補救措施而且錯誤信息會在控制臺打印。


現(xiàn)在我們常規(guī)await的處理方案有以下幾種。
第一種,手動添加啊try{}catch{}進行捕獲
我們可以通過手動給async函數(shù)內(nèi)部添加*try{}catch{}*來進行錯誤捕獲,如此,就可以避免錯誤在控制臺打印和阻塞代碼的運行。如下

這種做法的弊端是:需要捕獲錯誤的async多的話。每一個都寫下去,就比較麻煩和不可讀了。
第二種,使用await-to-js庫
網(wǎng)上總有大牛幫我們解決這些問題。await-to-js是一個幫助我們解決異步錯誤處理的庫,知名度較高,到目前有2.7k的?。
import to from "await-to-js";
//模擬請求
const handleFetch = async () => {
fetch("/url",{})
}
//進行錯誤捕獲和處理
const [err, result] = await to(handleFetch());
if (err) {
//進行錯誤動作處理
}這是一種比較簡單的處理方式
源碼 ---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 tots版本的源碼可能不便于閱讀,以下是我翻譯成js版本的源碼 ,并附加注解
export function to(
promise,
errorExt,
) {
return promise
//成功,則error返回null,result返回data
.then((data) => [null, data])
//錯誤則捕獲錯誤內(nèi)容,然后返回錯誤信息,result為undefined
.catch((err) => {
if (errorExt) {
const parsedError = Object.assign({}, err, errorExt);
return [parsedError, undefined];
}
return [err, undefined];
});
}最后
相較于自己使用try和catch進行捕獲,我更喜歡使用await-to-js這個庫,簡單方便,而且貼近hooks的寫法讓我覺得親切。
是否有必要給每一個請求都加上一個錯誤捕獲?我想是不需要的。我們需要知道,錯誤捕獲并不是無償?shù)摹T诤芏嗲闆r下我們并不需要去做這種特殊的處理,比如獲取分頁數(shù)據(jù)等。一般情況,只需要給一些可能會出現(xiàn)問題的async/await做這個處理即可。
總結
捕獲async和await的方法有兩種
- 手動添加try{}catch{}
- 使用await-to-js異步錯誤處理庫
到此這篇關于await/async無法捕獲與處理錯誤信息的解決方案的文章就介紹到這了,更多相關await/async無法捕獲與處理錯誤內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
如何解決JavaScript中的數(shù)組長度不對的問題
JavaScript?中的數(shù)組長度是一個比較常見的坑,理解數(shù)組長度的工作原理非常重要,下面就跟隨小編一起來了解下如何解決JavaScript中的數(shù)組長度不對的問題吧2024-12-12
JS實現(xiàn)的系統(tǒng)調(diào)色板完整實例
這篇文章主要介紹了JS實現(xiàn)的系統(tǒng)調(diào)色板,結合完整實例形式分析了js實現(xiàn)調(diào)色板效果的具體步驟與實現(xiàn)技巧,涉及js數(shù)值計算與頁面元素操作的方法,需要的朋友可以參考下2016-12-12

