在JavaScript/TypeScript的異步編程中,async/await讓我們的代碼看起來更像是同步的,極大地提高了可讀性。然而,錯誤處理仍然是一個需要仔細考慮的問題。今天我要分享一種優雅的錯誤處理模式,它能讓你的異步代碼更加簡潔。
傳統try-catch的問題
我們通常這樣處理異步錯誤:
async function fetchData() {try {const response = await fetch('api/data');const data = await response.json();// 處理數據} catch (error) {// 處理錯誤console.error('Fetch failed:', error);}
}
這種方式雖然有效,但當有多個await操作時,代碼會變得冗長,而且所有錯誤都會被同一個catch塊捕獲,難以區分錯誤來源。
更優雅的解決方案:awaitTo
下面介紹一個簡單的工具函數,它能改變我們處理異步錯誤的方式:
/*** 異步函數包裝器,用于處理異步函數的錯誤* @example const [err, res] = await awaitTo(promise)*/
const awaitTo = (promise: Promise<any>) => promise.then((res) => [null, res]).catch((err) => [err, null]);
使用示例
async function fetchData() {const [err, data] = await awaitTo(fetch('api/data').then(r => r.json()));if (err) {console.error('Fetch failed:', err);return;}// 安全地使用dataconsole.log('Data:', data);
}
多個異步操作的場景
async function fetchMultiple() {const [userErr, user] = await awaitTo(getUser());const [postsErr, posts] = await awaitTo(getPosts());if (userErr || postsErr) {// 可以精確知道哪個請求失敗了console.error('Errors:', { userErr, postsErr });return;}// 安全地使用user和postsconsole.log({ user, posts });
}
為什么這種模式更好?
- 更簡潔:避免了嵌套的try-catch塊
- 更明確:每個異步操作都有獨立的錯誤變量
- 更靈活:可以輕松處理部分成功的情況
- Go語言風格:類似于Go語言的多返回值錯誤處理模式
注意事項
- 這種方法不適合需要自動重試或復雜錯誤恢復的場景
- 對于簡單的單個異步操作,傳統try-catch可能更直接
- 確保在所有代碼路徑上都處理了錯誤
總結
awaitTo
這個小工具為async/await提供了另一種"食用方法",讓我們的異步代碼更加簡潔明了。它特別適合需要同時處理多個獨立異步操作的場景。不妨在你的下一個項目中試試這種模式,看看它是否能提升你的開發體驗!
你平時如何處理異步錯誤?歡迎在評論區分享你的經驗和看法。