介面請求失敗、介面中部分資料缺失、營運資料不符合預期… 當我們的應用程式發佈上線後,就開始面臨這些風險。
而一旦這些問題導致了 JavaScript 報錯(如空指針異常),並且沒有被有效地隔離,就有可能引發頁面的白屏、無法交互等線上問題。
在雙 11 準備期間,我們收集了過往一年前端相關的線上問題,在收集的 21 個案例中,竟有一半的問題都與“數據異常觸發頁顯示異常”這個原因有些相關。
如何將錯誤的影響隔離在一定範圍內,顯得尤為重要。
這篇文章就和大家一起來聊一聊我們嘗試過的一些方案,及遇到的問題。
從空指針異常說起
資料引發的最常見的問題就是空指針異常。
var result = a.b.c.d;
這樣的程式碼如同地雷,一旦 a 是一個動態數據,那麼問題一觸即發。
封裝一個 get 的方法來取值,當資料不存在時,傳回 undefined ,可以快速避免此類問題。
var result = get(a, 'b.c.d'); 但如同我们期望大家在取值前,都先做判断一样,并不能保证所有人都这么用了,用不用全靠自觉。 if (a && a.b && a.b.c) { var result = a.b.c.d; }
所以,有了以下的一些方案:
異步資料校驗
對異步數據校驗的想法是,數據在數據獲取後、使用前檢測數據缺失、類型不對等異常情況。
與此方案對應的,我們在 fetch 的基礎上封裝了 fetch-checker 註1 元件。
fetch-checker 強制要求使用者在請求資料的同時,提供資料對應的schema:
let schema = { "rule": { "type": "string", }, "banner": { "type": "object", "required": true, "default": { "url": "https://item.taobao.com/item.htm?id=527331762117" } } };
這份schema 需要描述:『 當required 的欄位缺失時,是否需要打底資料
fetch-checker 在拿到資料後,先做一層校驗,如有需要的話,補上缺失的數據,然後再回傳給呼叫者。這樣,用戶拿到的資料就一定是符合預期的。
然而,這個方案面臨的挑戰是:
如何確保呼叫者提供了完整的 schema 描述。不想寫 schema,完全可以提供一個粗略的 schema 描述,來通過校驗。
schema 如何精簡。即不會對 bundle 大小造成太大影響,又能滿足校驗的功能。
程式碼編譯
受 babel 的啟發,這個方案是對存在 NPE 隱患的程式碼,在編譯階段,將其轉換成等價的安全程式碼。如下圖所示:
var a = {}; // input var result = a.b.c; // output var result = (_object2 = (_object3 = a) == null ? null : _object3.b) == null ? null : _object2.c;
這個方案相比來說接入成本較低,開發者無需對現有的程式碼做出調整,但同樣存在挑戰: 開發階段問題不易暴露,明明應該報錯的場景,卻沒有任何反饋。理想的狀態是:開發調試階段盡可能多的暴露問題,線上則盡可能的減少報錯。
隱患的代碼如何界定。目前所有的 a.b 的調用方式都會按上述方案進行編譯,雖然測試過程中還沒有發現問題,但只處理有隱患的程式碼才更安全。
靜態校驗
以 flow 为代表的静态校验工具,可以在一定程度上检测出 NPE 隐患。 type res = { data ?: Object } let name = res.data.name; // property `name`. Propery cannot be accessed on possibly undefined value
以上就是JavaScript 中的錯誤隔離的內容,更多相關內容請關注PHP中文網(www.php.cn)!