JavaScript()錯誤處理
阿新 • • 發佈:2021-08-23
錯誤傳播
如果程式碼發生了錯誤,又沒有被try ... catch捕獲,那麼,程式執行流程會跳轉到哪呢?
function getLength(s) { return s.length; } function printLength() { console.log(getLength('abc')); // 3 console.log(getLength(null)); // Error! } printLength();
如果在一個函式內部發生了錯誤,它自身沒有捕獲,錯誤就會被拋到外層呼叫函式,如果外層函式也沒有捕獲,該錯誤會一直沿著函式呼叫鏈向上丟擲,直到被JavaScript引擎捕獲,程式碼終止執行。
所以,我們不必在每一個函式內部捕獲錯誤,只需要在合適的地方來個統一捕獲,一網打盡:
'use strict'; function main(s) { console.log('BEGIN main()'); try { foo(s); } catch (e) { console.log('出錯了:' + e); } console.log('END main()'); } function foo(s) { console.log('BEGIN foo()'); bar(s); console.log('END foo()'); } function bar(s) { console.log('BEGIN bar()'); console.log('length = ' + s.length); console.log('END bar()'); } main(null); /*執行結果: BEGIN main() BEGIN foo() BEGIN bar() 出錯了:TypeError: Cannot read property 'length' of null END main() */
當bar()
函式傳入引數null
時,程式碼會報錯,錯誤會向上拋給呼叫方foo()
foo()
函式沒有try ... catch語句,所以錯誤繼續向上拋給呼叫方main()
函式,main()
函式有try ... catch語句,所以錯誤最終在main()
函式被處理了。
至於在哪些地方捕獲錯誤比較合適,需要視情況而定。
非同步錯誤處理
編寫JavaScript程式碼時,我們要時刻牢記,JavaScript引擎是一個事件驅動的執行引擎,程式碼總是以單執行緒執行,而回調函式的執行需要等到下一個滿足條件的事件出現後,才會被執行。
例如,setTimeout()
函式可以傳入回撥函式,並在指定若干毫秒後執行
function printTime() { console.log('It is time!'); } setTimeout(printTime, 1000); console.log('done');
上面的程式碼會先列印done
,1秒後才會列印It is time!
。
如果printTime()
函式內部發生了錯誤,我們試圖用try包裹setTimeout()
是無效的:
'use strict'; function printTime() { throw new Error(); } try { setTimeout(printTime, 1000); console.log('done'); } catch (e) { console.log('error'); }
//執行結果
//done
原因就在於呼叫setTimeout()
函式時,傳入的printTime
函式並未立刻執行!緊接著,JavaScript引擎會繼續執行console.log('done');
語句,而此時並沒有錯誤發生。直到1秒鐘後,執行printTime
函式時才發生錯誤,但此時除了在printTime
函式內部捕獲錯誤外,外層程式碼並無法捕獲。
所以,涉及到非同步程式碼,無法在呼叫時捕獲,原因就是在捕獲的當時,回撥函式並未執行。
類似的,當我們處理一個事件時,在繫結事件的程式碼處,無法捕獲事件處理函式的錯誤。
例如,針對以下的表單:
<form> <input id="x"> + <input id="y"> <button id="calc" type="button">計算</button> </form>宣告 歡迎轉載,但請保留文章原始出處:) 部落格園:https://www.cnblogs.com/chenxiaomeng/ 如出現轉載未宣告 將追究法律責任~謝謝合作