首頁  >  文章  >  web前端  >  JavaScript 中的錯誤隔離

JavaScript 中的錯誤隔離

伊谢尔伦
伊谢尔伦原創
2016-11-21 13:52:081451瀏覽

介面請求失敗、介面中部分資料缺失、營運資料不符合預期… 當我們的應用程式發佈上線後,就開始面臨這些風險。

  而一旦這些問題導致了 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 為空物件時,執行編譯後的程式碼會傳回 null ,從而避免因為程式碼拋錯,阻斷後續進程。



  在 babel-plugin-safe-member-expression 註2 這個 Babel 插件中,我們做了上述的嘗試。目前,cake專案中,已經可以透過 enableSafeMemberExpression 這個配置,選擇性的啟用該功能。

  這個方案相比來說接入成本較低,開發者無需對現有的程式碼做出調整,但同樣存在挑戰:  開發階段問題不易暴露,明明應該報錯的場景,卻沒有任何反饋。理想的狀態是:開發調試階段盡可能多的暴露問題,線上則盡可能的減少報錯。

  隱患的代碼如何界定。目前所有的 a.b 的調用方式都會按上述方案進行編譯,雖然測試過程中還沒有發現問題,但只處理有隱患的程式碼才更安全。

  靜態校驗


  以 flow 为代表的静态校验工具,可以在一定程度上检测出 NPE 隐患。
type res = {
        data ?: Object
}
let name = res.data.name;
// property `name`. Propery cannot be accessed on possibly undefined value


如上面的程式碼所描述的,使用者需要先理清自己的資料是否允許為空值,當data 被允許為空值時,透過flow 偵測, data.name類似這樣呼叫便會被偵測出錯誤。



  然而,如何來推進所有的業務都接入靜態校驗,接入後,又如何保證開發者描述了所有的類型,卻同樣是個難點。

以上就是JavaScript 中的錯誤隔離的內容,更多相關內容請關注PHP中文網(www.php.cn)!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn