你有沒有經歷過這種時刻—— try 塊里一切正常, catch (e) 只打了一行日志,六個月后收到一個空白屏幕的 bug 報告?你花了三個小時回溯,才發現那個靜默吞下異常的 catch 塊。
這就是 Dart 中基于異常的錯誤處理的根本問題:異常在函數簽名里是隱形的,調用位置拿不到任何類型信息。編譯器根本不知道一個函數會失敗,自然也幫不上忙。于是每一條失敗路徑都成了作者和調用者之間的“社交契約”——這種契約在團隊擴大、凌晨兩點處理線上事故時,往往一觸即潰。
![]()
我們可以看一個橫跨全棧的實際例子:倉庫函數返回 Future<User> ,用例直接透傳, ViewModel 用 try/catch 包裹調用。表面合理,背后卻藏著致命隱患。簽名 Future<User> 告訴調用者“你會得到一個 User ”,對網絡故障、令牌過期、JSON 解析失敗只字不提。調用者必須讀了實現才知道可能出錯。一旦 ViewModel 忘了 try/catch ,代碼依然編譯通過,真正的崩潰只會發生在生產環境、真實用戶眼前。
更糟的是, catch (e) 會捕獲一切。變量拼寫錯誤、空引用、真正的網絡失敗——這些原本性質完全不同的問題,最終都落進同一個 catch 塊。這顯然不是生產級應用該有的樣子。
現在有一種更現代的錯誤處理方式,正在真實 Flutter 生產代碼庫中落地。我們不會止步于“避免異常”,而是從 Dart Records 這類輕量結果容器開始,構建一個密封 Result 類型;接著把它擴展到 Monad 模式,整合 dartz 包提供的函數式 Either 類型;最后借助 Freezed 創建類型化、窮舉的異常。整個過程走下來,失敗將變成類型化、可見、編譯器強制、無法再被忽略的存在。
在開始之前,你需要準備一個 Dart 3.0 或更高版本的 Flutter 項目,對 Dart 泛型、 async/await 有基本了解,理解密封類的概念,并能在項目中正常使用 freezed、freezed_annotation、build_runner 以及 dartz 包。
沿著這條路徑走下去,你代碼中的每一次失敗都不會再悄無聲息地溜走——它們會被看見、被檢查,最終被妥善處理。
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.