有時我們會忽略錯誤處理和堆棧追蹤的一些細節, 但是這些細節對于寫與測試或錯誤處理相關的庫來說是非常有用的. 例如這周, 對于 Chai 就有一個非常棒的PR, 該PR極大地改善了我們處理堆棧的方式, 當用戶的斷言失敗的時候, 我們會給予更多的提示信息(幫助用戶進行定位).
合理地處理堆棧信息能使你清除無用的數據, 而只專注于有用的數據. 同時, 當更好地理解 Errors 對象及其相關屬性之后, 能有助于你更充分地利用 Errors.
(函數的)調用棧是怎么工作的
在談論錯誤之前, 先要了解下(函數的)調用棧的原理:
當有一個函數被調用的時候, 它就被壓入到堆棧的頂部, 該函數運行完成之后, 又會從堆棧的頂部被移除.
堆棧的數據結構就是后進先出, 以 LIFO (last in, first out) 著稱.
例如:
function c() { console.log('c');} function b() { console.log('b'); c();} function a() { console.log('a'); b();} a();在上述的示例中, 當函數 a 運行時, 其會被添加到堆棧的頂部. 然后, 當函數 b 在函數 a 的內部被調用時, 函數 b 會被壓入到堆棧的頂部. 當函數 c 在函數 b 的內部被調用時也會被壓入到堆棧的頂部.
當函數 c 運行時, 堆棧中就包含了 a, b 和 c(按此順序).
當函數 c 運行完畢之后, 就會從堆棧的頂部被移除, 然后函數調用的控制流就回到函數 b. 函數 b 運行完之后, 也會從堆棧的頂部被移除, 然后函數調用的控制流就回到函數 a. 最后, 函數 a 運行完成之后也會從堆棧的頂部被移除.
為了更好地在demo中演示堆棧的行為, 可以使用 console.trace() 在控制臺輸出當前的堆棧數據. 同時, 你要以從上至下的順序閱讀輸出的堆棧數據.
function c() { console.log('c'); console.trace();} function b() { console.log('b'); c();} function a() { console.log('a'); b();} a();在 Node 的 REPL 模式中運行上述代碼會得到如下輸出:
Trace at c (repl:3:9) at b (repl:3:1) at a (repl:3:1) at repl:1:1 // <-- For now feel free to ignore anything below this point, these are Node's internals at realRunInThisContextScript (vm.js:22:35) at sigintHandlersWrap (vm.js:98:12) at ContextifyScript.Script.runInThisContext (vm.js:24:12) at REPLServer.defaultEval (repl.js:313:29) at bound (domain.js:280:14) at REPLServer.runBound [as eval] (domain.js:293:12)
正如所看到的, 當從函數 c 中輸出時, 堆棧中包含了函數 a, b 以及c.
如果在函數 c 運行完成之后, 在函數 b 中輸出當前的堆棧數據, 就會看到函數 c 已經從堆棧的頂部被移除, 此時堆棧中僅包括函數 a 和 b.
function c() { console.log('c');} function b() { console.log('b'); c(); console.trace();} function a() { console.log('a'); b();}正如所看到的, 函數 c 運行完成之后, 已經從堆棧的頂部被移除.
Trace at b (repl:4:9) at a (repl:3:1) at repl:1:1 // <-- For now feel free to ignore anything below this point, these are Node's internals at realRunInThisContextScript (vm.js:22:35) at sigintHandlersWrap (vm.js:98:12) at ContextifyScript.Script.runInThisContext (vm.js:24:12) at REPLServer.defaultEval (repl.js:313:29) at bound (domain.js:280:14) at REPLServer.runBound [as eval] (domain.js:293:12) at REPLServer.onLine (repl.js:513:10)
Error對象和錯誤處理
當程序運行出現錯誤時, 通常會拋出一個 Error 對象. Error 對象可以作為用戶自定義錯誤對象繼承的原型.
Error.prototype 對象包含如下屬性:
constructor 主站蜘蛛池模板: 连云港市| 永修县| 泗洪县| 久治县| 亚东县| 依安县| 泌阳县| 慈溪市| 商都县| 玉溪市| 河东区| 遂川县| 新宁县| 镇宁| 循化| 仲巴县| 涞源县| 平凉市| 昌都县| 元谋县| 尚义县| 肃宁县| 册亨县| 张家港市| 青神县| 安西县| 新宾| 邵武市| 改则县| 黔西县| 通州区| 青海省| 宾川县| 陕西省| 乌兰浩特市| 枣阳市| 九江市| 壤塘县| 雅江县| 达拉特旗| 江都市|