代碼質量第 4 層 - 健壯的代碼

點擊一鍵訂閱《雲薦大咖》專欄,獲取官方推薦精品內容,學技術不迷路!

健壯性(Robustness) 是指程序在遇到規範以外的輸入,錯誤和異常時,仍能正常運行。簡單來說,健壯代碼的適應性很強,不會因爲一些異常,就導致程序崩潰。

不健壯的前端代碼體現爲:

  • 接口返回異常或報錯時,頁面白屏。
  • 用戶做一些非常規操作時,頁面白屏。

如何寫出健壯的前端代碼


要寫出健壯的前端代碼,就要處理規範以外的輸入,錯誤和異常。具體來說,有 4 點:

  1. 異常處理。
  2. 輸入檢查。
  3. 寫法優化。
  4. 第三方庫的選擇。

下面,我們具體來說。

1. 異常處理

不做異常做處理,輕則導致功能出錯,重則導致頁面白屏。異常處理,可以分爲如下幾種情況。

主動捕獲運行時異常

try-catch 捕獲同步代碼的運行時錯誤。如果是異步代碼,需要轉化成 await 的寫法。如:

try {
  doSth()
  awaitdoSth2()
} catch (e) {
  // 處理異常
}

處理意料之外的全局運行時異常

未被處理的 JavaScript 運行時錯誤(包括語法錯誤)發生時, window 會觸發 error 事件。這麼處理:

window.addEventListener(
  'error',
  (e) => {/* 處理異常 */}
)

當一項資源(如<img><script>)加載失敗時,加載資源的元素會觸發 error 事件。這麼處理:

const img = new Image();
img.addEventListener(
  'error',
  (e) => {/* 處理異常 */}
)
img.src = 'xxx'

異步代碼: Promise reject 的處理

Promise 被 reject 時,可以在 then 的第二個參數或 catch 中處理。如:

p().then(onSuccess, onReject)
p().catch(onReject)

Promise reject 沒有被處理的話,window 會觸發 unhandledrejection 事件。可以統一來處理:

window.addEventListener(
  'unhandledrejection',
  (e) => {/* 處理異常 */}
)

用 Axios 時,接口報錯的通用處理

可以在 Axios 接口返回的攔截器中,加入接口報錯的通用處理。例如:

axios.interceptors.response.use(function (response) {
  return response;
}, err => {
  // 報錯處理
  if(err.response) {
    switch (err.response.status) {
      case 400: err.message = '請求錯誤(400)'; break;
      case 500: err.message = '服務器錯誤(500)'; break;
      // ...
    }
  }
  return Promise.reject(error);
})

Vue 的異常處理

app.config.errorHandler = (err, vm, info) => {
  // 處理異常
}

React 的異常處理

React 的生命週期函數 ComponentDidCatch 可以捕獲子組件的異常。因此,可以在根組件外包裹一個組件來處理錯誤。如:

class ErrorBoundary extends React.Component {
  componentDidCatch(error, info) {
    // 處理異常
  }
}

使用:

<ErrorBoundary>
  <App />
</ErrorBoundary>

2 輸入檢查

當輸入不滿足條件時,要儘早返回或主動報錯。這裏的輸入包括:接口的返回結果,函數的參數,組件的屬性等。

接口返回格式檢查

接口的返回會出現和前端預期不一致的情況。原因可能是:

  • 接口的返回結果變更,但未通知前端。
  • 一些特殊的請求參數,導致接口的返回和預期值不同。

因此,我們要對接口返回格式做檢查。我們來看個例子:

const res = await fetchList()
const list = res.map(...)

如果接口返回的不是數組,程序就會報錯。可以做類似這樣的優化:

const res = await fetchList()
const list = Array.isArray(res) ? res.map(...) : []

函數參數檢查

JavaScript 是弱類型語言,函數的參數可以傳任意值或不傳參。因此,不對函數參數檢查,會出現一些和預期不一致的情況。比如,期望實現兩數求和的功能:

function sum (a, b) {
  return a + b
}

sum(3, 4) // 7。和預期一致
sum() // NaN。和預期不一致
sum('3', 4) // '34'。和預期不一致

對函數參數做檢查,可以這麼優化:

function sum (a, b) {
  if(isNaN(parseFloat(a)) || isNaN(parseFloat(b))) {
    throw 'param error. param should be a num'
  }
  return parseFloat(a) + parseFloat(b)
}

推薦使用 TypeScript。可以用它檢查函數參數。上面的代碼用 TypeScript 這麼寫:

function sum (a: number | string, b: number | string) {
  return parseFloat(a as string) + parseFloat(b as string)
}

組件屬性檢查

對組件的屬性檢查和函數參數檢查類似,就不做贅述了。

3 寫法優化

很多寫法優化能提升代碼健壯性。這裏介紹 2 點。

1 switch 都需要有 default 來做異常或默認情況的處理。

2 訪問對象或數組前要做判斷

如:a.b.c 改成 a && a.b && a.b.c。如果用了 TypeScript,可以這麼寫: a?.b?.c

4 第三方庫的選擇

使用第三庫,可以減少造輪子,從而提升開發效率。但如果第三方包不健壯,用到第三方包的功能也就不健壯了。

健壯的第三方庫是成熟,穩定的。最好不要選擇以下情況的第三方庫:

  • 剛出來不久的。
  • 還沒出穩定版的。如果庫遵循的是 語意化版本規範,主版本號爲 0 的都不是穩定版。
  • 使用人數很少的。下載量少,star數低。
  • 沒有代碼測試的。

健壯性的測試方法


可以用猴子測試來測試代碼的健壯性。

猴子測試(Money Test),也稱搞怪測試。在軟件測試中,測試者可以進行各種稀奇古怪的操作模式,用以測試軟件的健壯性。

這裏推薦一個適用於瀏覽器的猴子測試工具:gremlins.js。工具會對要測試的頁面進行一通亂點。如下圖所示:

提升代碼質量的下一步


提升代碼質量的下一步就是提升代碼的可讀性。我會在下一篇文章中介紹。

 

 

 

金偉強往期精彩文章推薦:

聊聊代碼質量 - 《學得會,抄得走的提升前端代碼質量方法》前言

代碼質量第 5 層 - 只是實現了功能

《雲薦大咖》是騰訊雲加社區精品內容專欄。雲薦官特邀行業佼者,聚焦於前沿技術的落地及理論實踐之上,持續爲您解讀雲時代熱點技術、探索行業發展新機。點擊一鍵訂閱,我們將爲你定期推送精品內容。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章