這種情況有多常見?
function writeTransactionsToFile(transactions) { let writeStatus; try { fs.writeFileSync('transactions.txt', transactions); writeStatus = 'success'; } catch (error) { writeStatus = 'error'; } // do something with writeStatus...}
這是另一個我們想要一個取決于是否存在異常的值的實例。
通常, 我們可能會在 try-catch 的范圍之外創建一個可變變量,以便在其中和之后無錯誤地訪問。
但情況并非總是這樣。只要有一個函數式的 try-catch 就不會這樣。
一個純粹的 tryCatch() 函數避免了可變變量,并在我們的代碼庫中鼓勵可維護性和可預測性。
沒有修改外部狀態 - tryCatch() 封裝了整個錯誤處理邏輯并產生單一輸出。
我們的 catch 變成了一個不需要大括號的單行代碼:
function writeTransactionsToFile(transactions) { // 我們現在可以使用 const 了 const writeStatus = tryCatch({ tryFn: () => { fs.writeFileSync('transactions.txt', transactions); return 'success'; }, catchFn: (error) => 'error' }); // do something with writeStatus...}
那么,這個 tryCatch() 函數究竟是什么樣子的呢?
從我們以上的使用方式,你已經可以猜到定義了:
function tryCatch({ tryFn, catchFn }) { try { return tryFn(); } catch (error) { return catchFn(error); }}
為了正確地講述函數的作用,我們確保使用對象參數來明確參數名稱——即使只有兩個屬性。
因為編程不僅僅是達到目的的手段 - 我們還在講述從開始到結束的代碼庫中的對象和數據的故事。
TypeScript 在這樣的情況下非常好用;我們看看一個泛型類型的 tryCatch() 可能是什么樣子:
type TryCatchProps<T> = { tryFn: () => T; catchFn: (error: any) => T;};function tryCatch<T>({ tryFn, catchFn }: TryCatchProps<T>): T { try { return tryFn(); } catch (error) { return catchFn(error); }}
我們用 TypeScript 重寫功能性 writeTransactionsToFile() :
function writeTransactionsToFile(transactions: string) { // 返回 'success' 或 'error' const writeStatus = tryCatch<'success' | 'error'>({ tryFn: () => { fs.writeFileSync('transaction.txt', transactions); return 'success'; }, catchFn: (error) => return 'error'; }); // do something with writeStatus...}
我們使用 'success' | 'error' 聯合類型來限制我們可以從 try 和 catch 回調中返回的字符串。
不,我們完全不需要擔心這個問題 - 如果 tryFn 或 catchFn 是 async ,那么 writeTransactionToFile() 會自動返回一個 Promise 。
這是我們大多數人應該熟悉的另一個 try-catch 情況:發出網絡請求并處理錯誤。
在這里,我們根據請求是否成功來設置一個外部變量(在try-catch 之外)——在 React 應用中,我們可以輕松地用它設置狀態。
顯然,在真實世界的應用程序中,請求將會是異步的,以避免阻塞用戶界面線程:
async function comment(comment: string) { type Status = 'error' | 'success'; let commentStatus: Status; try { const response = await fetch('https://api.mywebsite.com/comments', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ comment }), }); if (!response.ok) { commentStatus = 'error'; } else { commentStatus = 'success'; } } catch (error) { commentStatus = 'error'; } // do something with commentStatus...}
我們再次需要在這里創建一個可變變量,以便它可以進入 try-catch 并且沒有作用域錯誤地成功出來。
我們像以前一樣進行重構,這次,我們 async 了 try 和 catch 函數,從而 await 了 tryCatch() :
async function comment(comment: string) { type Status = 'error' | 'success'; // ?? await because this returns Promise<Status> const commentStatus = await tryCatch<Status>({ tryFn: async () => { const response = await fetch('https://api.mywebsite.com/comments', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ comment }), }); // ?? functional conditional return response.ok ? 'success' : 'error'; }, catchFn: async (error) => 'error', }); // do something with commentStatus...}
處理異常時遵循的兩個 try-catch 經驗法則:
他們將使你的代碼在短期和長期內更易于閱讀和維護。看看這里的 processJSONFile()
本文鏈接:http://www.tebozhan.com/showinfo-26-96430-0.html函數式 try-catch 如何轉變 JavaScript 代碼
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com