日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

捕捉到了异常继续循环_前端异常处理最佳实践

發(fā)布時(shí)間:2024/9/19 HTML 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 捕捉到了异常继续循环_前端异常处理最佳实践 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前端可以說是最貼近用戶的一層,當(dāng)產(chǎn)品不斷的迭代完善,產(chǎn)品的用戶體驗(yàn)會(huì)更加趨向于完美,然而前端異常卻是很另人頭疼的一個(gè)問題,我們應(yīng)該怎么去對待這些異常呢?

一、為什么要處理異常?

異常是不可控的,會(huì)影響最終的呈現(xiàn)結(jié)果,但是我們有充分的理由去做這樣的事情。

  • 增強(qiáng)用戶體驗(yàn);
  • 遠(yuǎn)程定位問題;
  • 未雨綢繆,及早發(fā)現(xiàn)問題;
  • 無法復(fù)線問題,尤其是移動(dòng)端,機(jī)型,系統(tǒng)都是問題;
  • 完善的前端方案,前端監(jiān)控系統(tǒng);
  • 對于 JS 而言,我們面對的僅僅只是異常,異常的出現(xiàn)不會(huì)直接導(dǎo)致 JS 引擎崩潰,最多只會(huì)使當(dāng)前執(zhí)行的任務(wù)終止。

    二、需要處理哪些異常?

    對于前端來說,我們可做的異常捕獲還真不少。總結(jié)一下,大概如下:

    • JS 語法錯(cuò)誤、代碼異常
    • AJAX 請求異常
    • 靜態(tài)資源加載異常
    • Promise 異常
    • Iframe 異常
    • 跨域 Script error
    • 崩潰和卡頓

    下面我會(huì)針對每種具體情況來說明如何處理這些異常。

    三、Try-Catch 的誤區(qū)

    try-catch 只能捕獲到同步的運(yùn)行時(shí)錯(cuò)誤,對語法和異步錯(cuò)誤卻無能為力,捕獲不到。

    1、同步運(yùn)行時(shí)錯(cuò)誤:

    輸出:

    2、不能捕獲到語法錯(cuò)誤,我們修改一下代碼,刪掉一個(gè)單引號(hào):


    輸出:


    不過語法錯(cuò)誤在我們開發(fā)階段就可以看到,應(yīng)該不會(huì)順利上到線上環(huán)境。

    3、異步錯(cuò)誤


    可以看看日志:


    并沒有捕獲到異常,這是需要我們特別注意的地方。

    四、window.onerror 不是萬能的

    當(dāng) JS 運(yùn)行時(shí)錯(cuò)誤發(fā)生時(shí),window 會(huì)觸發(fā)一個(gè) ErrorEvent 接口的 error 事件,并執(zhí)行 window.onerror()。

    1、首先試試同步運(yùn)行時(shí)錯(cuò)誤


    可以看到,我們捕獲到了異常:

    2、再試試語法錯(cuò)誤呢?


    控制臺(tái)打印出了這樣的異常:


    竟然沒有捕獲到語法錯(cuò)誤?

    3、懷著忐忑的心,我們最后來試試異步運(yùn)行時(shí)錯(cuò)誤:

    控制臺(tái)輸出了:

    4、接著,我們試試網(wǎng)絡(luò)請求異常的情況:


    我們發(fā)現(xiàn),不論是靜態(tài)資源異常,或者接口異常,錯(cuò)誤都無法捕獲到。

    補(bǔ)充一點(diǎn):window.onerror 函數(shù)只有在返回 true 的時(shí)候,異常才不會(huì)向上拋出,否則即使是知道異常的發(fā)生控制臺(tái)還是會(huì)顯示 Uncaught Error: xxxxx


    控制臺(tái)就不會(huì)再有這樣的錯(cuò)誤了:

    需要注意:

    • onerror 最好寫在所有 JS 腳本的前面,否則有可能捕獲不到錯(cuò)誤;
    • onerror 無法捕獲語法錯(cuò)誤;

    到這里基本就清晰了:在實(shí)際的使用過程中,onerror 主要是來捕獲預(yù)料之外的錯(cuò)誤,而 try-catch 則是用來在可預(yù)見情況下監(jiān)控特定的錯(cuò)誤,兩者結(jié)合使用更加高效。

    問題又來了,捕獲不到靜態(tài)資源加載異常怎么辦?

    一、window.addEventListener

    當(dāng)一項(xiàng)資源(如圖片或腳本)加載失敗,加載資源的元素會(huì)觸發(fā)一個(gè) Event 接口的 error 事件,并執(zhí)行該元素上的onerror() 處理函數(shù)。這些 error 事件不會(huì)向上冒泡到 window ,不過(至少在 Firefox 中)能被單一的window.addEventListener 捕獲。


    控制臺(tái)輸出:


    由于網(wǎng)絡(luò)請求異常不會(huì)事件冒泡,因此必須在捕獲階段將其捕捉到才行,但是這種方式雖然可以捕捉到網(wǎng)絡(luò)請求的異常,但是無法判斷 HTTP 的狀態(tài)是 404 還是其他比如 500 等等,所以還需要配合服務(wù)端日志才進(jìn)行排查分析才可以。

    需要注意:

    不同瀏覽器下返回的 error 對象可能不同,需要注意兼容處理。
    需要注意避免 addEventListener 重復(fù)監(jiān)聽。

    二、Promise Catch

    在 promise 中使用 catch 可以非常方便的捕獲到異步 error ,這個(gè)很簡單。沒有寫 catch 的 Promise 中拋出的錯(cuò)誤無法被 onerror 或 try-catch 捕獲到,所以我們務(wù)必要在 Promise 中不要忘記寫 catch 處理拋出的異常。

    解決方案:為了防止有漏掉的 Promise 異常,建議在全局增加一個(gè)對 unhandledrejection 的監(jiān)聽,用來全局監(jiān)聽Uncaught Promise Error。使用方式:


    我們繼續(xù)來嘗試一下:


    那如果對 Promise 不進(jìn)行 catch 呢?


    嗯,事實(shí)證明,也是會(huì)被正常捕獲到的。

    所以,正如我們上面所說,為了防止有漏掉的 Promise 異常,建議在全局增加一個(gè)對 unhandledrejection 的監(jiān)聽,用來全局監(jiān)聽 Uncaught Promise Error。

    補(bǔ)充一點(diǎn):如果去掉控制臺(tái)的異常顯示,需要加上:

    三、VUE errorHandler

    四、React 異常捕獲

    React 16 提供了一個(gè)內(nèi)置函數(shù) componentDidCatch,使用它可以非常簡單的獲取到 react 下的錯(cuò)誤信息


    UI 的某部分引起的 JS 錯(cuò)誤不應(yīng)該破壞整個(gè)程序,為了幫 React 的使用者解決這個(gè)問題,React 16 介紹了一種關(guān)于錯(cuò)誤邊界(error boundary)的新觀念。

    需要注意的是:error boundaries 并不會(huì)捕捉下面這些錯(cuò)誤。

  • 事件處理器
  • 異步代碼
  • 服務(wù)端的渲染代碼
  • 在 error boundaries 區(qū)域內(nèi)的錯(cuò)誤
  • 我們來舉一個(gè)小例子,在下面這個(gè) componentDIdCatch(error,info) 里的類會(huì)變成一個(gè) error boundary:


    然后我們像使用普通組件那樣使用它:


    componentDidCatch() 方法像 JS 的 catch{} 模塊一樣工作,但是對于組件,只有 class 類型的組件(class component )可以成為一個(gè) error boundaries 。

    實(shí)際上,大多數(shù)情況下我們可以在整個(gè)程序中定義一個(gè) error boundary 組件,之后就可以一直使用它了!

    五、iframe 異常

    對于 iframe 的異常捕獲,我們還得借力 window.onerror:


    一個(gè)簡單的例子可能如下:

    六、Script error

    一般情況,如果出現(xiàn) Script error 這樣的錯(cuò)誤,基本上可以確定是出現(xiàn)了跨域問題。這時(shí)候,是不會(huì)有其他太多輔助信息的,但是解決思路無非如下:

    跨源資源共享機(jī)制( CORS ):我們?yōu)?script 標(biāo)簽添加 crossOrigin 屬性。


    或者動(dòng)態(tài)去添加 js 腳本:


    特別注意,服務(wù)器端需要設(shè)置:Access-Control-Allow-Origin
    此外,我們也可以試試這個(gè)-解決 Script Error 的另類思路:

    簡單解釋一下:

    改寫了 EventTarget 的 addEventListener 方法;

    對傳入的 listener 進(jìn)行包裝,返回包裝過的 listener,對其執(zhí)行進(jìn)行 try-catch;

    瀏覽器不會(huì)對 try-catch 起來的異常進(jìn)行跨域攔截,所以 catch 到的時(shí)候,是有堆棧信息的;

    重新 throw 出來異常的時(shí)候,執(zhí)行的是同域代碼,所以 window.onerror 捕獲的時(shí)候不會(huì)丟失堆棧信息;

    利用包裝 addEventListener,我們還可以達(dá)到「擴(kuò)展堆棧」的效果

    七、崩潰和卡頓

    卡頓也就是網(wǎng)頁暫時(shí)響應(yīng)比較慢, JS 可能無法及時(shí)執(zhí)行。但崩潰就不一樣了,網(wǎng)頁都崩潰了,JS 都不運(yùn)行了,還有什么辦法可以監(jiān)控網(wǎng)頁的崩潰,并將網(wǎng)頁崩潰上報(bào)呢?

    崩潰和卡頓也是不可忽視的,也許會(huì)導(dǎo)致你的用戶流失。

    1、利用window對象的load和beforeunload事件實(shí)現(xiàn)了對網(wǎng)頁崩潰的監(jiān)控。

    2、基于以下原因,我們可以使用service Worker來實(shí)現(xiàn)對網(wǎng)頁崩潰的監(jiān)控。

    • Service Worker 有自己獨(dú)立的工作線程,與網(wǎng)頁區(qū)分開,網(wǎng)頁崩潰了,Service Worker 一般情況下不會(huì)崩潰;
    • Service Worker 生命周期一般要比網(wǎng)頁還要長,可以用來監(jiān)控網(wǎng)頁的狀態(tài);
    • 網(wǎng)頁可以通過 navigator.serviceWorker.controller.postMessage API 向掌管自己的 SW 發(fā)送消息。

    八、錯(cuò)誤上報(bào)

    1、通過 Ajax 發(fā)送數(shù)據(jù)
    因?yàn)?Ajax 請求本身也有可能會(huì)發(fā)生異常,而且有可能會(huì)引發(fā)跨域問題,一般情況下更推薦使用動(dòng)態(tài)創(chuàng)建 img 標(biāo)簽的形式進(jìn)行上報(bào)。

    2、動(dòng)態(tài)創(chuàng)建 img 標(biāo)簽的形式

    收集異常信息量太多,怎么辦?實(shí)際中,我們不得不考慮這樣一種情況:如果你的網(wǎng)站訪問量很大,那么一個(gè)必然的錯(cuò)誤發(fā)送的信息就有很多條,這時(shí)候,我們需要設(shè)置采集率,從而減緩服務(wù)器的壓力:


    采集率應(yīng)該通過實(shí)際情況來設(shè)定,隨機(jī)數(shù),或者某些用戶特征都是不錯(cuò)的選擇。

    九、總結(jié)

    回到我們開頭提出的那個(gè)問題,如何優(yōu)雅的處理異常呢?

  • 可疑區(qū)域增加 Try-Catch
  • 全局監(jiān)控 JS 異常 window.onerror
  • 全局監(jiān)控靜態(tài)資源異常 window.addEventListener
  • 捕獲沒有 Catch 的 Promise 異常:unhandledrejection
  • VUE errorHandler 和 React componentDidCatch
  • 監(jiān)控網(wǎng)頁崩潰:window 對象的 load 和 beforeunload
  • 跨域 crossOrigin 解決
  • 其實(shí)很簡單,采用組合方案,分類型的去捕獲異常,這樣基本 80%-90% 的問題都化于無形。

    如果您在學(xué)習(xí)編程的過程中遇到難題,歡迎關(guān)注微信公眾號(hào)【筑夢前端】,大家一起交流解決!

    總結(jié)

    以上是生活随笔為你收集整理的捕捉到了异常继续循环_前端异常处理最佳实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。