精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

不用try catch,如何機(jī)智的捕獲錯(cuò)誤

開(kāi)發(fā)
這是多個(gè)feature組合使用后實(shí)現(xiàn)的神奇效果,在React源碼中被廣泛使用。當(dāng)我讀源碼看到這里時(shí),心情經(jīng)歷了:懵逼 -- 困惑 -- 沉思 -- 查文檔 -- 豁然開(kāi)朗,看完此文,相信你也會(huì)發(fā)出感嘆:還能這么玩?

[[344042]]

起源
我們知道,React中有個(gè)特性Error Boundary,幫助我們?cè)诮M件發(fā)生錯(cuò)誤時(shí)顯示“錯(cuò)誤狀態(tài)”的UI。

為了實(shí)現(xiàn)這個(gè)特性,就一定需要捕獲到錯(cuò)誤。

所以在React源碼中,所有用戶(hù)代碼都被包裹在一個(gè)方法中執(zhí)行。

類(lèi)似如下: 

  1. function wrapper(func) { 
  2.   try { 
  3.     func(); 
  4.   } catch(e) { 
  5.     // ...處理錯(cuò)誤 
  6.   } 

比如觸發(fā)componentDidMount時(shí):

  1. wrapper(componentDidMount); 

本來(lái)一切都很完美,但是React作為世界級(jí)前端框架,受眾廣泛,凡事都講究做到極致。

這不,有人提issue:

  1. 你們這樣在try catch中執(zhí)行用戶(hù)代碼會(huì)讓瀏覽器調(diào)試工具的Pause on exceptions失效。 

Pause on exceptions失效的來(lái)龍去脈
Pause on exceptions是什么?

他是瀏覽器調(diào)試工具source面板的一個(gè)功能。

開(kāi)啟該功能后,在運(yùn)行時(shí)遇到會(huì)拋出錯(cuò)誤的代碼,代碼的執(zhí)行會(huì)自動(dòng)停在該行,就像在該行打了斷點(diǎn)一樣。

比如,執(zhí)行如下代碼,并開(kāi)啟該功能:

  1. let a = c; 

代碼的執(zhí)行會(huì)在該行暫停。

這個(gè)功能可以很方便的幫我們發(fā)現(xiàn)未捕獲的錯(cuò)誤發(fā)生的位置。

但是,當(dāng)React將用戶(hù)代碼包裹在try catch后,即使代碼拋出錯(cuò)誤,也會(huì)被catch。

Pause on exceptions無(wú)法在拋出錯(cuò)誤的用戶(hù)代碼處暫停,因?yàn)閑rror已經(jīng)被React catch了。

除非我們進(jìn)一步開(kāi)啟Pause on caught exceptions。

開(kāi)啟該功能,使代碼在捕獲的錯(cuò)誤發(fā)生的位置暫停。

如何解決
對(duì)用戶(hù)來(lái)說(shuō),我寫(xiě)在componentDidMount中的代碼明明未捕獲錯(cuò)誤,可是錯(cuò)誤發(fā)生時(shí)Pause on exceptions卻失效了,確實(shí)有些讓人困惑。

所以,在生產(chǎn)環(huán)境,React繼續(xù)使用try catch實(shí)現(xiàn)wrapper。

而在開(kāi)發(fā)環(huán)境,為了更好的調(diào)試體驗(yàn),需要重新實(shí)現(xiàn)一套try catch機(jī)制,包含如下功能:

  • 捕獲用戶(hù)代碼拋出的錯(cuò)誤,使Error Boundary功能正常運(yùn)行
  • 不捕獲用戶(hù)代碼拋出的錯(cuò)誤,使Pause on exceptions不失效

這看似矛盾的功能,React如何機(jī)智的實(shí)現(xiàn)呢?

如何“捕獲”錯(cuò)誤
讓我們先實(shí)現(xiàn)第一點(diǎn):捕獲用戶(hù)代碼拋出的錯(cuò)誤。

但是不能使用try catch,因?yàn)檫@會(huì)讓Pause on exceptions失效。

解決辦法是:監(jiān)聽(tīng)window的error事件。

根據(jù)GlobalEventHandlers.onerror MDN[1],該事件可以監(jiān)聽(tīng)到兩類(lèi)錯(cuò)誤:

  • js運(yùn)行時(shí)錯(cuò)誤(包括語(yǔ)法錯(cuò)誤)。window會(huì)觸發(fā)ErrorEvent接口的error事件
  • 資源(如<img>或<script>)加載失敗錯(cuò)誤。加載資源的元素會(huì)觸發(fā)Event接口的error事件,可以在window上捕獲該錯(cuò)誤

實(shí)現(xiàn)開(kāi)發(fā)環(huán)境使用的wrapperDev:

  1. // 開(kāi)發(fā)環(huán)境wrapper 
  2. function wrapperDev(func) { 
  3.   function handleWindowError(error) { 
  4.     // 收集錯(cuò)誤交給Error Boundary處理 
  5.   } 
  6.  
  7.   window.addEventListener('error', handleWindowError); 
  8.   func(); 
  9.   window.removeEventListener('error', handleWindowError); 

當(dāng)func執(zhí)行時(shí)拋出錯(cuò)誤,會(huì)被handleWindowError處理。

但是,對(duì)比生產(chǎn)環(huán)境wrapperPrd內(nèi)func拋出的錯(cuò)誤會(huì)被catch,不會(huì)影響后續(xù)代碼執(zhí)行。

  1. function wrapperPrd(func) { 
  2.   try { 
  3.     func(); 
  4.   } catch(e) { 
  5.     // ...處理錯(cuò)誤 
  6.   } 

開(kāi)發(fā)環(huán)境func內(nèi)如果拋出錯(cuò)誤,代碼的執(zhí)行會(huì)中斷。

比如執(zhí)行如下代碼,finish會(huì)被打印。

  1. wrapperPrd(() => {throw Error(123)}) 
  2. console.log('finish'); 

但是執(zhí)行如下代碼,代碼執(zhí)行中斷,finish不會(huì)被打印。

  1. wrapperDev(() => {throw Error(123)}) 
  2. console.log('finish'); 

如何在不捕獲用戶(hù)代碼拋出錯(cuò)誤的前提下,又能讓后續(xù)代碼的執(zhí)行不中斷呢?

如何讓代碼執(zhí)行不中斷
答案是:通過(guò)dispatchEvent觸發(fā)事件回調(diào),在回調(diào)中調(diào)用用戶(hù)代碼。

根據(jù)EventTarget.dispatchEvent MDN[2]:

不同于DOM節(jié)點(diǎn)觸發(fā)的事件(比如click事件)回調(diào)是由event loop異步觸發(fā)。

通過(guò)dispatchEvent觸發(fā)的事件是同步觸發(fā),并且在事件回調(diào)中拋出的錯(cuò)誤不會(huì)影響dispatchEvent的調(diào)用者(caller)。

讓我們繼續(xù)改造wrapperDev。

首先創(chuàng)建虛構(gòu)的DOM節(jié)點(diǎn)、事件對(duì)象、虛構(gòu)的事件類(lèi)型:

  1. // 創(chuàng)建虛構(gòu)的DOM節(jié)點(diǎn) 
  2. const fakeNode = document.createElement('fake'); 
  3. // 創(chuàng)建event 
  4. const event = document.createEvent('Event'); 
  5. // 創(chuàng)建虛構(gòu)的event類(lèi)型 
  6. const evtType = 'fake-event'

初始化事件對(duì)象,監(jiān)聽(tīng)事件。在事件回調(diào)中調(diào)用用戶(hù)代碼。觸發(fā)事件:

  1. function callCallback() { 
  2.   fakeNode.removeEventListener(evtType, callCallback, false);  
  3.   func(); 
  4.  
  5. // 監(jiān)聽(tīng)虛構(gòu)的事件類(lèi)型 
  6. fakeNode.addEventListener(evtType, callCallback, false); 
  7.  
  8. // 初始化事件 
  9. event.initEvent(evtType, falsefalse); 
  10.  
  11. // 觸發(fā)事件 
  12. fakeNode.dispatchEvent(event); 

完整流程如下:

  1. function wrapperDev(func) { 
  2.   function handleWindowError(error) { 
  3.     // 收集錯(cuò)誤交給Error Boundary處理 
  4.   } 
  5.    
  6.   function callCallback() { 
  7.     fakeNode.removeEventListener(evtType, callCallback, false);  
  8.     func(); 
  9.   } 
  10.    
  11.   const event = document.createEvent('Event'); 
  12.   const fakeNode = document.createElement('fake'); 
  13.   const evtType = 'fake-event'
  14.  
  15.   window.addEventListener('error', handleWindowError); 
  16.   fakeNode.addEventListener(evtType, callCallback, false); 
  17.  
  18.   event.initEvent(evtType, falsefalse); 
  19.    
  20.  
  21.   fakeNode.dispatchEvent(event); 
  22.    
  23.   window.removeEventListener('error', handleWindowError); 

當(dāng)我們調(diào)用:

  1. wrapperDev(() => {throw Error(123)}) 

會(huì)依次執(zhí)行:

  • dispatchEvent觸發(fā)事件回調(diào)callCallback
  • 在callCallback內(nèi)執(zhí)行到throw Error(123),拋出錯(cuò)誤
  • callCallback執(zhí)行中斷,但調(diào)用他的函數(shù)會(huì)繼續(xù)執(zhí)行。
  • Error(123)被window error handler捕獲用于Error Boundary

其中步驟2使Pause on exceptions不會(huì)失效。

步驟3、4使得錯(cuò)誤被捕獲,且不會(huì)阻止后續(xù)代碼執(zhí)行,模擬了try catch的效果。

總結(jié)
不得不說(shuō),React這波操作真細(xì)啊。

我們實(shí)現(xiàn)的迷你wrapper還有很多不足,比如:

 

  • 沒(méi)有針對(duì)不同瀏覽器的兼容
  • 沒(méi)有考慮其他代碼也觸發(fā)window error handler

React源碼的完整版wrapper,見(jiàn)這里[3]參考資料

 

[1]

GlobalEventHandlers.onerror MDN: https://developer.mozilla.org/zh-CN/docs/Web/API/GlobalEventHandlers/onerror

[2]

EventTarget.dispatchEvent MDN: https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/dispatchEvent

[3]

這里: https://github.com/facebook/react/blob/master/packages/shared/invokeGuardedCallbackImpl.js#L63-L237

 

 

責(zé)任編輯:姜華 來(lái)源: 魔術(shù)師卡頌
相關(guān)推薦

2021-01-05 07:54:55

事項(xiàng)trycatch

2017-11-02 15:26:10

JavaScriptasync錯(cuò)誤

2023-09-07 07:53:21

JavaScriptGoRust

2020-08-24 13:35:59

trycatchJava

2024-11-13 01:00:18

asyncawait?編程

2025-04-29 08:05:00

JavaScript錯(cuò)誤處理開(kāi)發(fā)

2025-02-12 12:00:00

前端try-catchJavaScrip

2024-06-25 10:37:11

2023-11-13 17:01:26

C++編程

2024-11-28 08:33:18

前端代碼報(bào)錯(cuò)

2025-07-03 07:05:00

JavaScriptPromise代碼

2024-05-24 08:59:15

2025-08-07 06:05:00

try/catch前端JavaScrip

2009-12-02 19:56:33

PHP中try{}ca

2021-03-31 11:52:24

try-catch-fJava代碼

2022-06-16 10:37:09

asyncawait

2023-05-16 15:32:45

JavaScriptWeb前端工程師

2020-06-15 08:12:51

try catch代碼處理器

2025-01-16 12:00:00

try-catchfor循環(huán)

2025-03-10 08:10:00

安全賦值運(yùn)算符ECMAScript編碼
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

少妇高潮av久久久久久| 国产视频久久久久久| av超碰免费在线| www.久久精品| 国产精品综合网站| 国产在线观看免费视频今夜| 欧美人体视频| 欧美美女一区二区| 国产妇女馒头高清泬20p多| 欧美日韩国产亚洲沙发| 国产美女av一区二区三区| 2019中文字幕全在线观看| 久久人妻无码aⅴ毛片a片app| 欧洲亚洲成人| 欧美一级黄色录像| 国产精品视频黄色| 美女搞黄视频在线观看| 亚洲免费成人av| 日本亚洲自拍| 日本在线一二三| 国产成人午夜视频| 国产专区欧美专区| 波多野结衣在线观看视频| 激情久久久久久| 久久精品男人天堂| 91成人精品一区二区| 欧美在线导航| 亚洲精品一区二区三区蜜桃下载| 亚洲三级视频网站| 欧美电影免费观看| 天天色综合天天| h无码动漫在线观看| 黄网站视频在线观看| 欧美韩国日本不卡| 久久av一区二区三区漫画| 亚洲av无码一区二区三区性色 | 亚洲一区二区三区免费| 精品视频全国免费看| 激情网站五月天| 午夜激情在线播放| 黄色成人在线播放| 激情五月宗合网| 多野结衣av一区| 亚洲第一搞黄网站| 日韩精品免费一区| 色屁屁www国产馆在线观看| 成人欧美一区二区三区1314| 一道精品一区二区三区| 欧美极品另类| 亚洲日本欧美天堂| 激情视频小说图片| www久久日com| 亚洲一区二区视频在线观看| 成人av在线不卡| 青青在线视频| 午夜精品一区二区三区免费视频 | 日韩av一区二区在线影视| 国产91成人video| 国产三级av片| 日韩中文字幕不卡| 国产精品人人做人人爽| 一本色道久久综合亚洲| 久久99精品网久久| 91亚色免费| 狠狠躁日日躁夜夜躁av| av午夜精品一区二区三区| 久久精品午夜一区二区福利| 可以直接在线观看的av| 国产精品国产自产拍高清av王其| 超碰在线免费观看97| 宅男网站在线免费观看| 亚洲成人自拍网| 日本wwww视频| 欧美在线se| 欧美精品一区二区三| 无码人妻精品一区二区三区温州| 欧洲专线二区三区| 久久精品视频在线播放| 国产无码精品在线播放| 免费看黄裸体一级大秀欧美| 国产精品专区h在线观看| 国产黄频在线观看| 91蜜桃在线免费视频| 亚洲一区二区四区| 成人超碰在线| 欧美性猛交xxxx黑人交| 亚洲一二区在线观看| 久9re热视频这里只有精品| 亚洲品质视频自拍网| 日韩成人毛片视频| 亚洲专区欧美专区| 91在线无精精品一区二区| 天天操天天干天天| 国产精品盗摄一区二区三区| 国产av人人夜夜澡人人爽麻豆| 日韩大尺度黄色| 欧美一区二区精品久久911| 青青草视频播放| 91精品国产自产在线观看永久∴| 欧美又大粗又爽又黄大片视频| 999在线免费视频| 日本少妇一区| 精品欧美一区二区久久| 九九热久久免费视频| 亚洲大黄网站| 成人a级免费视频| 欧美色视频免费| 亚洲综合色自拍一区| 中文字幕永久视频| 国产日韩三级| 久久国产精品免费视频 | 粗大黑人巨茎大战欧美成人| 欧美日韩亚洲视频一区| 亚洲欧美日韩中文字幕在线观看| 黑丝美女一区二区| 亚洲91精品在线| 99久久精品无免国产免费| 国产亚洲福利社区一区| 久久99中文字幕| 欧美成年网站| 日韩中文字幕视频| 日韩电影在线观看一区二区| 成人h动漫精品一区二区| 在线观看免费黄色片| 欧美大片免费观看网址| 日韩黄在线观看| www.youjizz.com亚洲| 国内精品伊人久久久久av影院| 欧美一区二区影视| 日产福利视频在线观看| 亚洲国产日韩精品在线| 国产黄色片视频| 国产成人日日夜夜| 欧美另类videosbestsex日本| 青青国产精品| www.欧美精品| 亚洲一区在线观| 国产精品网曝门| 亚洲激情在线观看视频| 精品国产乱码久久久久久蜜坠欲下| 9.1国产丝袜在线观看| 高清毛片aaaaaaaaa片| 亚洲一区二区在线观看视频| 久久黄色一级视频| 欧美精品不卡| 国产91免费视频| 国产偷倩在线播放| 精品va天堂亚洲国产| 国产精品99无码一区二区| 国产不卡一区视频| 大荫蒂性生交片| 北条麻妃一区二区三区在线观看| 欧美日韩成人在线播放| www.色日本| 亚洲v中文字幕| 毛茸茸多毛bbb毛多视频| 老妇喷水一区二区三区| 日日骚一区二区网站| 草民电影神马电影一区二区| 上原亚衣av一区二区三区| 国产又大又长又粗| 亚洲乱码日产精品bd| 久久久久中文字幕亚洲精品| 极品少妇一区二区三区| 精品久久久久久亚洲| 一区二区视频免费完整版观看| 这里只有精品视频在线| 国产巨乳在线观看| 亚洲午夜三级在线| 精品夜夜澡人妻无码av| 麻豆久久久久久久| 天堂av在线中文| 玖玖玖免费嫩草在线影院一区| 日本aⅴ大伊香蕉精品视频| av在线女优影院| 日韩视频中午一区| 国产欧美日韩另类| 国产精品网曝门| 午夜影院福利社| 丝袜a∨在线一区二区三区不卡| 亚洲高清视频一区| 51社区在线成人免费视频| 38少妇精品导航| 欧美精品videos另类| 精品国产网站在线观看| 337p粉嫩色噜噜噜大肥臀| 亚洲精品视频免费观看| 中文字幕在线观看网址| 久久se这里有精品| 一二三四视频社区在线| 91视频久久| 免费久久一级欧美特大黄| 自拍偷拍亚洲图片| 2018日韩中文字幕| 国产成人无吗| 国产亚洲人成网站在线观看| 国产成人精品免费看视频| 色悠久久久久综合欧美99| 最新一区二区三区| 国产日韩精品一区二区浪潮av | 亚洲国产欧美在线观看| 国产99视频精品免视看7| 亚洲wwwww| 尤物tv国产一区| 手机看片国产1024| 制服丝袜中文字幕一区| 中文字幕在线欧美| 亚洲午夜一区二区| 亚洲欧美精品aaaaaa片| 久久久久久久久久看片| 精品人妻一区二区乱码| 久久中文在线| 亚洲人精品午夜射精日韩 | 久久亚洲国产精品| 国产中文字幕在线播放| 亚洲福利影片在线| 精品人妻av一区二区三区| 欧美三区在线观看| 无码人妻丰满熟妇奶水区码| 性久久久久久久久| 激情五月少妇a| ●精品国产综合乱码久久久久 | 免费观看国产视频| 日韩一区二区视频| 91theporn国产在线观看| 在线观看亚洲一区| 东京热一区二区三区四区| 香蕉影视欧美成人| 国产亚洲精品久久777777| 亚洲日本在线观看| 久久人妻无码aⅴ毛片a片app| 国产欧美日韩中文久久| 天堂久久精品忘忧草| 99国产精品国产精品毛片| 佐佐木明希电影| 国产激情视频一区二区在线观看| 亚洲第一区第二区第三区| 久久精品国产一区二区三区免费看| 日韩毛片在线免费看| 噜噜噜久久亚洲精品国产品小说| 你懂的av在线| 性欧美暴力猛交另类hd| 丰满少妇被猛烈进入高清播放| 亚洲免费播放| 国产男女无遮挡| 久久经典综合| 激情 小说 亚洲 图片: 伦| 日韩精品五月天| 性生活免费在线观看| 久草热8精品视频在线观看| 亚洲天堂av一区二区三区| 国产精品综合久久| 潘金莲一级淫片aaaaaaa| 成人性生交大片免费看视频在线| 亚洲精品国产成人av在线| 成人高清视频免费观看| 久久丫精品国产亚洲av不卡| 国产亚洲成年网址在线观看| 天堂网av2018| 一区二区三区在线观看欧美| 国产一级特黄毛片| 欧美午夜精品久久久久久浪潮| 久久久蜜桃一区二区| 欧美精品在线观看播放| 亚洲第一天堂影院| 亚洲精品一区二区三区不| av电影在线观看网址| 久久精品99久久久香蕉| 日韩伦理av| 日韩av电影在线播放| 亚洲精品三区| 成人欧美一区二区三区黑人免费| 亚洲精华一区二区三区| 亚洲日本精品| 在线观看一区| 亚洲欧美国产日韩综合| 国产一区在线精品| 黄色污在线观看| 中文字幕 久热精品 视频在线| 1024手机在线视频| 欧美性xxxx极品高清hd直播| 一区二区日韩在线观看| 欧美精品一区二区高清在线观看| 国产黄在线观看| 精品自拍视频在线观看| 成人免费直播| av免费观看久久| 国产精品探花在线观看| 久久香蕉视频网站| 三级亚洲高清视频| 国产精品19p| 国产日产欧美一区二区三区| 欧美精品videos极品| 日本精品视频一区二区| xxxx国产精品| 在线观看国产欧美| xxxx另类黑人| 成人妇女淫片aaaa视频| 思热99re视热频这里只精品| 可以免费看的黄色网址| 葵司免费一区二区三区四区五区| 国产精久久久久| 久久久久久久电影| 国产在线视频卡一卡二| 欧美日本视频在线| 免费在线性爱视频| 欧美激情视频在线免费观看 欧美视频免费一| 亚洲最新无码中文字幕久久| 国产经典一区二区三区| 久久亚洲国产| 国产一二三四在线视频| 99热这里都是精品| 一区二区三区免费高清视频| 欧美久久久久久久久久| 黄色av网址在线免费观看| 欧美精品xxx| 久久伊人精品| 亚洲一区精品视频| 日韩国产一区二| 成人午夜剧场视频网站| 亚洲成a天堂v人片| 精品人妻一区二区三区换脸明星| 日韩在线中文视频| 日韩久久一区二区三区| 欧美黑人xxxxx| 在线综合亚洲| 性色av蜜臀av色欲av| 亚洲午夜久久久久| www.中文字幕| 九九热在线精品视频| 亚洲男人在线| 欧美性视频在线播放| 精品在线免费观看| 天天色天天综合| 欧美日韩国产大片| 日本亚洲精品| 国产一区二区在线播放| 日韩精品一卡| 日本超碰在线观看| 国产精品成人一区二区艾草 | 欧美mv日韩mv国产网站| av免费在线观看网站| 亚洲一区二区自拍| 欧美91精品| 欧美熟妇精品一区二区| 亚洲综合色区另类av| 黄色www视频| 91精品国产电影| 一个色免费成人影院| 激情婷婷综合网| 欧美高清在线精品一区| 亚洲图片视频小说| 久久精品视频中文字幕| 欧洲一区在线| 欧美成人高潮一二区在线看| 91在线播放网址| 波多野结衣黄色| 精品久久久91| 婷婷视频一区二区三区| 可以看毛片的网址| 久久色.com| 一级黄色片免费看| 久久69精品久久久久久国产越南| 爱爱精品视频| www.色偷偷.com| 亚洲女与黑人做爰| 成人午夜免费福利| 国产成人精品优优av| 久久人体视频| 国产一卡二卡三卡四卡| 一本一本大道香蕉久在线精品| 91精品专区| 成人综合色站| 鲁大师成人一区二区三区| 91麻豆精品久久毛片一级| 日韩欧美高清dvd碟片| 亚洲淫成人影院| 97超碰免费观看| 成人h动漫精品一区二区| 久草热在线观看| 欧美国产一区二区三区| 欧美美女在线| 日韩av影视大全| 黑人巨大精品欧美一区二区| 9191在线观看| 国产在线精品一区二区中文| 蜜臀91精品一区二区三区 | 少妇av片在线观看| 精品久久久久久无| 欧美free嫩15| 日韩网站在线免费观看| 国产精品免费丝袜| 色屁屁草草影院ccyycom| 国产美女久久精品| 在线一区免费观看| 欧美日韩大片在线观看| 在线色欧美三级视频| 久久国产精品色av免费看| 男人的天堂最新网址| 91精品办公室少妇高潮对白|