精品欧美一区二区三区在线观看 _久久久久国色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)

亚洲精品videossex少妇| 亚洲制服欧美中文字幕中文字幕| 国产免费一区视频观看免费| 视频国产一区二区| 久久国产精品免费精品3p| 日本精品一区二区三区高清| 蜜臀av.com| 免费毛片在线| 国产传媒一区在线| 国产精品久久久久高潮| 18精品爽视频在线观看| 精品国产一区二区三区| 日韩精品中文字幕在线一区| 激情五月亚洲色图| 激情影院在线| 国产精品水嫩水嫩| 久久精品中文字幕一区二区三区| 97精品人妻一区二区三区香蕉 | 亚洲精品永久免费| 亚洲高清在线不卡| 国产精品极品美女在线观看| 性感美女久久精品| 制服丝袜综合日韩欧美| 蜜桃成人在线视频| 成人动漫精品一区二区| 成人在线国产精品| 免费在线不卡av| 国产欧美二区| 992tv在线成人免费观看| 中国一级片在线观看| 欧美一区二区三区激情视频| 日韩电影在线观看永久视频免费网站| 国产精品嫩草影院8vv8| 成人自拍视频网| 欧美日韩另类字幕中文| 大陆极品少妇内射aaaaaa| 日本三级在线播放完整版| 国产午夜精品在线观看| 欧美精品七区| 欧美日韩伦理片| 波多野洁衣一区| 国产福利久久| 不卡视频在线播放| 国产精品一区二区三区乱码| 91精品国产综合久久香蕉922| 免费看污视频的网站| 亚洲欧美视频| 欧美孕妇毛茸茸xxxx| 色播视频在线播放| 亚洲高清资源| 97精品视频在线观看| 国产无码精品一区二区| 伊人久久大香线蕉av超碰演员| 欧美高清视频在线播放| 久久精品www| 国产综合网站| 97精品欧美一区二区三区| 国产无遮挡aaa片爽爽| 亚洲电影av| 97久久久免费福利网址| 免费黄色网址在线| 米奇777在线欧美播放| 欧美亚洲伦理www| 日本免费精品视频| 蜜臀精品久久久久久蜜臀 | 国产婷婷色一区二区三区在线| 蜜桃av噜噜一区二区三| 北条麻妃在线| 亚洲女爱视频在线| 加勒比成人在线| 巨茎人妖videos另类| 欧美影视一区在线| 午夜天堂在线视频| 国产毛片精品| 亚洲欧美在线磁力| 女教师淫辱の教室蜜臀av软件| 99欧美视频| 久久久久久国产| 免费视频久久久| 另类中文字幕网| 岛国视频一区| 国产三级在线观看| 亚洲欧美日韩成人高清在线一区| 免费一级淫片aaa片毛片a级| 秋霞伦理一区| 欧美精品色一区二区三区| 亚洲精品鲁一鲁一区二区三区 | 99热国产在线观看| 日韩成人伦理电影在线观看| 91久久精品国产| 亚洲 欧美 精品| 中文字幕一区二区视频| 亚洲 欧美 综合 另类 中字| 毛片无码国产| 91精品国产91久久久久久一区二区 | 久久99久久亚洲国产| 久久国产精品免费看| 美女视频黄久久| 国产乱子伦精品| 日本美女在线中文版| 亚洲成av人影院| 99国产精品久久久久久| 日韩欧美中文字幕电影| 久久久成人的性感天堂| wwwwww国产| 国产成人在线视频网站| 色一情一区二区三区四区| 男人添女人下部高潮视频在线观看| 在线观看亚洲专区| 日本久久久久久久久久| 日韩国产一区二区| 日本不卡免费高清视频| 亚洲精品国产手机| 国产精品久久久久久久久免费桃花 | 日本中文字幕在线看| 精品福利免费观看| a级大片免费看| av一区二区在线播放| 午夜欧美不卡精品aaaaa| 国产精品久久久久久在线| 91麻豆国产香蕉久久精品| 免费视频爱爱太爽了| 亚洲在线资源| 一区二区三区在线播放欧美| 视频一区二区三区四区五区| 国产在线麻豆精品观看| 亚洲精品中文字幕在线| 欧美日韩成人影院| 日韩电影在线观看永久视频免费网站| 伊人365影院| 国产一区二区看久久| 一区二区三区四区欧美| 成人交换视频| 在线观看不卡av| www.色国产| 91麻豆视频网站| 日韩精品视频一区二区在线观看| 99re8这里有精品热视频8在线| 欧美大奶子在线| 国产99999| 亚洲精品福利视频网站| 热久久久久久久久| 一本精品一区二区三区| 91精品综合视频| 麻豆传媒在线完整视频| 这里只有精品视频在线观看| 强制高潮抽搐sm调教高h| 韩国欧美一区二区| 日本精品免费视频| 精品中文字幕一区二区三区| 欧美成人一区二区三区电影| 国产欧美久久久| 一区二区三区色| 黄色av网址在线观看| 亚洲经典视频在线观看| 激情视频一区二区| 蜜臀国产一区| 在线观看视频亚洲| 国产精品-色哟哟| 一区二区三区精品视频在线| 亚洲精品激情视频| 久久99伊人| 五月天国产一区| 国产在线一区不卡| 久久久久久久久国产| 青青草在线免费视频| 91高清视频免费看| 欧美一级特黄高清视频| 国产精品自拍毛片| 欧美黑人经典片免费观看| 国产一区99| 成人美女免费网站视频| 成人福利影视| 国产亚洲成av人片在线观看桃| 欧美激情一区二区三区免费观看 | 91精品国产自产观看在线 | 中文字幕在线观看一区二区三区| 大胆国模一区二区三区| 97香蕉久久夜色精品国产| 番号集在线观看| 欧美一级午夜免费电影| 成年免费在线观看| 国产精品嫩草影院com| 精品人妻二区中文字幕 | 亚洲精品中文字幕乱码无线| 亚洲网站视频| 日韩尤物视频| 亚洲一区二区三区免费| 国产福利视频一区二区| 97影院秋霞午夜在线观看| 亚洲国产精品va在线观看黑人| 日韩欧美国产另类| 一区二区三区加勒比av| 精品人妻中文无码av在线| 国产不卡高清在线观看视频| 北条麻妃在线视频| 一区在线免费| 制服国产精品| 国产成人精品免费视| 99三级在线| 久久国产三级| 欧美与黑人午夜性猛交久久久| 国产丝袜在线| 伊人亚洲福利一区二区三区| 欧美视频xxx| 欧美日韩高清一区二区| 亚洲不卡视频在线观看| 亚洲精品成人a在线观看| 精品人妻中文无码av在线 | 一本在线免费视频| 久久综合精品国产一区二区三区 | 欧美极品欧美精品欧美| 天天操夜夜操国产精品| 欧美在线视频二区| 国产欧美啪啪| 99re视频在线| 国产精品成人**免费视频| 国产精品久久久久免费a∨大胸 | 免费观看久久久久| 亚洲欧美精品suv| 天天干,夜夜爽| 欧美不卡一区二区三区四区| 91精品国自产| 欧美艳星brazzers| 免费污污视频在线观看| 第一福利永久视频精品| 国产无套内射又大又猛又粗又爽| 亚洲色图.com| 永久免费看mv网站入口| 亚洲国产精品av| a天堂中文字幕| 久久综合色8888| 双性尿奴穿贞c带憋尿| 99久久婷婷国产综合精品| 免费啪视频在线观看| 国产酒店精品激情| 九九九久久久久久久| 黑人巨大精品欧美一区| 欧洲在线免费视频| 国产乱码精品一区二区三区av| 99日在线视频| 精品无码三级在线观看视频| 欧美美女性视频| 久久99久久久久久久久久久| 手机看片一级片| 蜜桃av噜噜一区二区三区小说| 免费黄色一级网站| 蜜臀av性久久久久蜜臀aⅴ| 妓院一钑片免看黄大片| 免费成人美女在线观看| 国内av一区二区| 国产sm精品调教视频网站| 四虎永久免费观看| av色综合久久天堂av综合| 99久久人妻精品免费二区| 91在线视频18| 免费看污片的网站| 国产精品久久久久国产精品日日| 日韩在线观看免| 一区二区国产视频| 日韩 欧美 综合| 在线观看成人免费视频| 国产精品欧美激情在线| 精品国产伦一区二区三区观看体验 | 国产suv精品一区二区33| 一本久久a久久精品亚洲 | 精品粉嫩aⅴ一区二区三区四区| 成人久久久精品国产乱码一区二区| 亚洲福利视频在线| 国产免费a∨片在线观看不卡| 中文字幕国产日韩| 新版中文在线官网| 国产91|九色| 欧美成人高清视频在线观看| 99国产超薄肉色丝袜交足的后果 | 国产激情一区二区三区桃花岛亚洲| 国产乱国产乱老熟300部视频| 91麻豆免费在线观看| 色偷偷www8888| 精品成人乱色一区二区| 一级做a爱片性色毛片| 欧美xxxxxxxx| 麻豆国产在线播放| 操日韩av在线电影| 自拍在线观看| 亚洲iv一区二区三区| 日韩三区视频| 天天综合五月天| 久久xxxx| 能看毛片的网站| 欧美激情在线看| 日韩成人av毛片| 欧美精品一二三| 毛片网站在线观看| 欧美激情aaaa| 国产综合色激情| 免费看污久久久| 亚洲午夜在线| 午夜激情av在线| 91网页版在线| 欧美爱爱小视频| 欧美揉bbbbb揉bbbbb| 欧美性受xxxx狂喷水| 日韩一二三在线视频播| 伊人色综合一区二区三区影院视频 | 91video| 日韩欧美123| 色老头视频在线观看| 国产91露脸中文字幕在线| 亚洲视频国产| 伊人久久大香线蕉午夜av| 久久久久国产精品一区三寸| av电影在线播放| 亚洲欧美日韩久久| 啪啪小视频网站| 日韩激情第一页| 678在线观看视频| 91成人理论电影| 久久亚洲成人| av五月天在线| 久久久久久亚洲综合影院红桃| 国产污视频在线看| 精品国产免费人成在线观看| 影音先锋在线视频| 91精品国产自产在线观看永久| 久久av影视| 青青草原av在线播放| 波多野结衣精品在线| 精品午夜福利视频| 精品美女一区二区三区| 亚洲91av| 91久久久一线二线三线品牌| 91九色精品国产一区二区| 中文字幕第38页| 亚洲国产高清在线观看视频| 波多野结衣一区二区三区在线| 日韩电影大片中文字幕| 岛国在线视频网站| 久久久精品动漫| 国产精品一国产精品k频道56| 亚洲av成人无码一二三在线观看| 亚洲国产精品一区二区久久 | 国产精品一二三四五区| 中文字幕在线观看亚洲| 日韩有码欧美| 天堂av免费看| 国产.欧美.日韩| 国产成人啪精品午夜在线观看| 精品少妇一区二区三区在线视频| 丁香花在线高清完整版视频| 国产精品一国产精品最新章节| 欧美日本不卡| 亚洲制服丝袜在线播放| 欧美日韩激情美女| 国际av在线| 国产日韩欧美另类| 亚洲一区二区| 黄色在线免费播放| 欧美性生交xxxxx久久久| 韩国三级在线观看久| 国产伦精品免费视频| 亚洲电影影音先锋| 无码人妻久久一区二区三区蜜桃 | 中文字幕欧美人妻精品| 久久精品视频va| 中文字幕一区图| 啊啊啊一区二区| 国产精品欧美经典| www黄色网址| 热re91久久精品国99热蜜臀| 日韩久久精品| 欧美成人精品一区二区综合免费| 日韩人在线观看| 日本电影全部在线观看网站视频| 91gao视频| 日韩一区精品字幕| 91视频青青草| 日韩av网址在线| 亚洲欧美专区| 大陆极品少妇内射aaaaa| 国产精品女主播av| 污视频软件在线观看| 国产精品视频男人的天堂| 女人天堂亚洲aⅴ在线观看| 97人妻精品一区二区三区免| 欧美午夜片在线看| 好看的中文字幕在线播放| 日本一区二区三区四区高清视频 | 欧美日韩在线播放三区四区| 七七成人影院| 性欧美大战久久久久久久免费观看 | 国产91精品在线播放| 欧美成人午夜| 国产jk精品白丝av在线观看| 日韩免费高清av| 456亚洲精品成人影院| 成人午夜免费在线视频| 中文字幕精品三区| 亚洲av电影一区| 亚洲在线www|