一道不同的前端架構師最終面試題 【實用系列】

image.png

本次寫做來源於一次面試,前端架構師崗位,最後面試官臨時給我掏出了一道比較少見的面試題 ,終究斬獲offer ,雖然這道題並不難,可是考察的東西挺有趣,加上近期有看到前端防護性編程、優雅處理前端錯誤的文章,因而想起來把這道題寫了下來。html


這是一個關於前端錯誤處理的題目,由淺入深前端

本題答案: xxxx未定義,致命錯誤,以前無錯誤捕獲處理機制,頁面沒有跳轉到百度react


第二個版本:webpack

這裏仍是比較簡單,由於try裏面纔會捕獲錯誤,一旦拋出錯誤就會被全局捕獲錯誤的函數捕獲  最終輸出順序:    try  拋出錯誤   全局捕獲到錯誤git


加入函數調用版本,問最終打印臺輸出什麼 github

調用test,執行test,執行完了try同步代碼後,執行拋出Error,結束test的函數的調用(只要函數內部拋出錯誤,就會結束這個函數的調用而且出棧),全局捕獲到的錯誤,仍是‘拋出錯誤’這個咱們本身定義的錯誤內容,console.log(a)並無被執行到 web


變異版本 面試

這裏主要考察的是函數的拋出錯誤配合finally的執行,咱們一直認爲,只要函數內部拋出錯誤,就會結束這個函數調用,立馬出棧。因此return和throw new Error不能在一塊兒用,可是finally卻仍是依然會執行。finally,顧名思義,最後都會執行ajax

finally 語句在 try 和 catch 以後不管有無異常都會執行。數據庫


加入webpack工程化構建的變異版本,選中此html爲模板,問, 若是其餘經過webpack構建的文件發生了致命錯誤,例如由於作了tree sharking,沒有兼容低版本瀏覽器,此時能夠捕獲到全局錯誤嗎

答案是不能夠捕獲到,由於通過webpack打包後,代碼會變成

若是此時其餘模塊發生了致命錯誤,例如const這種代碼跑在IE6中,那麼就會直接致命錯誤,阻斷瀏覽器解析代碼,頁面掛掉。js引擎也不會去解析下面的代碼~ 尚未運行到window.onerror這裏就掛了


上面只是一個比較簡單的面試題,考察錯誤處理能力,後面是結合React的錯誤邊界,資源請求錯誤,ajax請求錯誤等的處理來口述,這裏可能須要你平時對這些東西有比較多瞭解和實踐才能hold住


window.onerror與window.addEventListener('error')捕獲js運行時錯誤

使用window.onerror和window.addEventListener('error')都能捕獲,可是window.onerror含有詳細的error堆棧信息,存在error.stack中,因此咱們選擇使用onerror的方式對js運行時錯誤進行捕獲。


資源加載錯誤使用addEventListener去監聽error事件捕獲

實現原理:當一項資源(如<img>或<script>)加載失敗,加載資源的元素會觸發一個Event接口的error事件,並執行該元素上的onerror()處理函數。

這些error事件不會向上冒泡到window,不過能被window.addEventListener在捕獲階段捕獲。

但這裏須要注意,因爲上面提到了addEventListener也可以捕獲js錯誤,所以須要過濾避免重複捕獲,判斷爲資源錯誤的時候才進行處理。

僞代碼

window.addEventListener('error', (e) => {

這樣就能夠捕獲到任意的圖片等資源加載錯誤的信息,可是捕獲後依舊會有爆紅提示,我猜測這種資源請求錯誤是很是重要的,必須爆出來?


Error Boundaries(錯誤邊界)配合webpack+系統的onerror錯誤捕獲

有人說使用 create-react-app 建立的項目,在開發環境,就算使用了 componentDidCatch 或者 getDerivedStateFromError,錯誤依然會被拋出,在 build 後,錯誤將會捕獲,不會致使整個項目卸載(這點我不肯定,由於我都是本身配腳手架的)

根據官方文檔所說,在 react 16 之後,任何未被錯誤邊界捕獲的錯誤將會致使整個 React 組件樹被卸載。因此咱們在開發項目時,須要去捕獲錯誤邊界的錯誤,並提供一個備用UI,那麼被錯誤邊界捕獲的錯誤,還會冒泡到window中嗎 


多說無益,咱們先實踐 

咱們先定義一個錯誤邊界,而後html模板文件中,依舊有咱們的那段代碼

此時將錯誤邊界組件包裹APP根組件~

運行代碼,一切正常 


此時React根組件的componentDidmount生命週期函數拋出錯誤

拋出錯誤後,被錯誤邊界捕獲 

說明這種錯誤被React錯誤邊界捕獲後,就不會再被onerror函數捕獲,那麼window.addEventListenr呢? 嘗試一下。

一樣,也沒有被捕獲,通過測試,dom2形式監聽error事件,不管第三個參數是false仍是true,只要被錯誤邊界捕獲後,都不會再被捕獲。


接下來是語法錯誤

若是是同步的語法錯誤,在try catch中就能夠被捕獲,不會冒泡到window.onerror事件中


異步語法錯誤

最終被全局到error回調函數捕獲,可是你們很奇怪,這裏爲何捕獲了,還會爆出錯誤?咱們以前是不會的。

這裏要說明一點,若是是人爲拋出錯誤 throw new Error,error函數是能夠捕獲的。可是一旦是語法錯誤,那麼須要在error函數中return true,這樣異常纔不會往上繼續拋出。


當咱們打開return true 時候

全局錯誤捕獲,而且控制檯不會出現未捕獲的錯誤了~


細心的朋友會發現,控制檯一直有一個報錯,沒錯,這是一個靜態資源的請求,img標籤。

項目中有一段這個代碼

<img src="ssss" alt=""/>

最終返回響應是:

**這裏能夠肯定,靜態資源請求錯誤,不會冒泡到window.error事件中,只能夠經過上面的dom2形式經過在捕獲階段捕獲到這個錯誤
**

window.addEventListener('error', (e) => {

dom2形式捕獲到了這個請求資源錯誤,並且同時觸發了這個標籤的onerror事件

<img src="ssss" alt="" onError={(e)=>{console.log('圖片加載失敗',e)}}/>

一些圖片的處理,能夠相似這樣,當請求的靜態資源出現錯誤時候,能夠更換請求地址

,不會致使碎圖


Promise的捕獲對於頻繁調用的函數,確定是須要封裝成promise風格的,統一處理錯誤,統一接口捕獲一次就能夠了由於onerror函數並不能捕獲promise錯誤,這裏我就不演示了

> 網絡請求錯誤也是不會被error函數捕獲的,可是咱們能夠封裝成promise風格,統一本身catch錯誤處理


因爲async await函數和promise可能比較多,項目中,爲了防止沒有捕獲的promise出現,咱們可使用 

這樣就能夠經過unhandledrejection這個事件捕獲到沒有處理錯誤的promise


對於錯誤上報,通常是採用不會跨域的請求,例如img標籤、audio標籤等靜態資源get請求後面將error信息拼接,後臺截取查詢字符串存入數據庫和緩存中提供記錄和查詢能力

new Image().src = `${url}?err=${error}`;

這樣後端就能夠接受到異常錯誤信息了

好久以前看過有用Performance和beforeunload, servece worker去處理極端狀況的,你們有興趣也能夠去看看,我這裏就不作過多的介紹,前者使用也比較簡單,後者並不太適用每一個人。

因爲如今的錯誤監控、上報已經造成了一套完整的商業鏈,這方面並非個人強項,若是寫得不對的地方,歡迎指出,架構師崗位面試,更考察你對項目總體把控能力,最後出現這個題目,我以爲也正常


本開源項目gitHub地址(React和webpack,練手適合):

https://github.com/JinJieTan/react-webpack

    若是感受寫得不錯,能夠幫忙點個-在看

    但願每一個人都會像老許同樣 

    有人問你,你要老婆/老公不要?

    要的話,就給你送來

相關文章
相關標籤/搜索