【Vue】淺出Vue 錯誤處理機制errorCaptured、errorHandler


引子

JavaScript本身是一個弱類型語言,項目中容易發生錯誤,做好網頁錯誤監控,能幫助開發者迅速定位問題,保證線上穩定。

介紹 errorHandler、errorCaptured

文檔傳送門: errorHandlererrorCaptured

errorHandler

指定組件的渲染和觀察期間未捕獲錯誤的處理函數。這個處理函數被調用時,可獲取錯誤信息和 Vue 實例

Vue.config.errorHandler = function (err, vm, info) {
  #處理錯誤信息, 進行錯誤上報
  #err錯誤對象
  #vm Vue實例
  #`info` 是 Vue 特定的錯誤信息,比如錯誤所在的生命周期鈎子
  #只在 2.2.0+ 可用
}
版本分割點
  • 2.2.0 起,捕獲組件生命周期鈎子里的錯誤。同樣的,當這個鈎子是 undefined 時,被捕獲的錯誤會通過 console.error 輸出而避免應用崩潰
  • 2.4.0 起,也會捕獲 Vue 自定義事件處理函數內部的錯誤
  • 2.6.0 起,也會捕獲 v-on DOM 監聽器內部拋出的錯誤。另外,如果任何被覆蓋的鈎子或處理函數返回一個 Promise 鏈 (例如 async 函數),則來自其 Promise 鏈的錯誤也會被處理

errorCaptured

當捕獲一個來自子孫組件的錯誤時被調用。此鈎子會收到三個參數:錯誤對象、發生錯誤的組件實例以及一個包含錯誤來源信息的字符串。此鈎子可以返回 false 以阻止該錯誤繼續向上傳播

錯誤傳播規則
  • 默認情況下,如果全局的 config.errorHandler定義,所有的錯誤仍會發送它,因此這些錯誤仍然會向單一的分析服務的地方進行匯報
  • 如果一個組件的繼承或父級從屬鏈路中存在多個 errorCaptured 鈎子,則它們將會被相同的錯誤逐個喚起。
  • 如果此 errorCaptured 鈎子自身拋出了一個錯誤,則這個新錯誤和原本被捕獲的錯誤都會發送給全局的 config.errorHandler,不能捕獲異步promise內部拋出的錯誤和自身的錯誤
  • 一個 errorCaptured 鈎子能夠返回 false 以阻止錯誤繼續向上傳播。本質上是說“這個錯誤已經被搞定了且應該被忽略”。它會阻止其它任何會被這個錯誤喚起的 errorCaptured 鈎子和全局的 config.errorHandler

錯誤信息示例 errorHandler、errorCaptured

1.errorHandler

vue 項目錯誤正常展示

示例代碼如下:

export default {
    created() {
        let a = null;
        if(a.length > 1) {
            // ...
        }
    }
};

正常情況下,上述代碼會報錯:

 

 vue 項目錯誤捕獲以及當中的缺陷

繼上面后,我們嘗試通過 Vue.config.errorHander 捕獲:

Vue.config.errorHandler = (err, vm, info) => {
    console.log('進來啦~');
}

export default {
    created() {
        let a = null;
        if(a.length > 1) {
            // ...
        }
    }
};

然后控制台就不會對外拋錯:

 

 那么在錯誤監控系統中,理論上我們只去捕獲報錯而不去攔截報錯,那么要怎么做才能把錯誤外拋到控制台呢?

簡單點,就加個console.error(err)

Vue.config.errorHandler = (err, vm, info) => {
    console.log('進來啦~');
    console.error(err);~~~~
}

export default {
    created() {
        let a = null;
        if(a.length > 1) {
            // ...
        }
    }
};

控制台將會得到下面截圖:

 

 那么這樣就可以了,錯誤的上報我們可以再Vue.config.errorHandler 中去做,完了再去把 Vue 中的這個“短板”補上,讓錯誤繼續正常拋出來。那么此時錯誤上報的函數(比如這函數是是captureError())應該這么去調用:

Vue.config.errorHandler = (err, vm, info) => {
    console.log('進來啦~');
    // 錯誤上報到收集報錯的平台
    captureError(err);
}

export default {
    created() {
        let a = null;
        if(a.length > 1) {
            // ...
        }
    }
};

2.errorCaptured (err, vm, info) => ?Boolean 類似於React 錯誤處理邊界

 

<error-boundary>
  <another-component/>
</error-boundary>
Vue.component('ErrorBoundary', {
  data: () => ({ error: null }),
  errorCaptured (err, vm, info) {
    this.error = `${err.stack}\n\nfound in ${info} of component`
    return false
  },
  render (h) {
    if (this.error) {
      return h('pre', { style: { color: 'red' }}, this.error)
    }
    // ignoring edge cases for the sake of demonstration
    return this.$slots.default[0]
  }
})

參考https://segmentfault.com/a/1190000018606181https://segmentfault.com/a/1190000021706923?utm_source=tag-newest


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM