摘要:一中的對象包含了錯(cuò)誤的具體信息,包括錯(cuò)誤堆棧等。不源碼了,特別簡單,自己去一下。
一. Error
二. 錯(cuò)誤拋出幾種方式????JS 中的 Error 對象. 包含了錯(cuò)誤的具體信息,包括 name、message、錯(cuò)誤堆棧 stack 等。可以以 new Error 方式創(chuàng)建實(shí)例拋出,或調(diào)用 Error.captureStackTrace 為已有對象添加 stack 錯(cuò)誤堆棧信息 而后拋出
三. 錯(cuò)誤捕獲幾種方式Throw
Javascript 拋出的異常,是以 throw 方法拋出,未必都是 Error 的實(shí)例,但通過 nodeJs 或者 js 運(yùn)行時(shí)發(fā)生的錯(cuò)誤,都是 Error 的實(shí)例EventEmitter
Nodejs 形式的錯(cuò)誤回調(diào),大部分流 & 異步事件都衍生自 EventEmitter 類 || 實(shí)例,如 fs, process, stream 等Process
程序運(yùn)行過程中拋出的異常,或由底層庫拋出,或是運(yùn)行中發(fā)生的一些 SyntaxError 之類
try .. catch
常用的一種捕獲錯(cuò)誤方式,瀏覽器 || node 環(huán)境均適用
缺點(diǎn):只針對同步異常有效
try { throw new Error("Something went wrong here") } catch (err) { console.log(err) }
EventEmitter
????由 Events 模塊提供的 EventEmitter 類,基于 Observer 模式做的 publish/subscribe,通過 .on("error", ...) || .addEventlistener("error", ...) 注冊 subscriber,.emit() 發(fā)布事件,但會(huì)有最大的 maxListener 的限制,可更改。
????不 show 源碼了,特別簡單,自己去 look 一下。如 koa 的 app 就是基于 EventEmitter 的擴(kuò)展,因此可以通過監(jiān)聽 error
class Koa extends EventEmitter {...} let app = new Koa() app.emit("error", ..) app.on("error", ...)
Process
Process 進(jìn)程對象也是 EventEmitter 的實(shí)例,可通過如下兩事件監(jiān)聽 error
unhandledRejection
????promise 的回調(diào)報(bào)錯(cuò),可通過監(jiān)聽該事件 catch,但要注意由于 promise 的 rejection catched 不知道會(huì)在啥時(shí)候才發(fā)生,所以實(shí)際上可能在 unhandledRejection 事件觸發(fā)后才 catch 了這個(gè)信息,對應(yīng)有 rejectionHandled 事件監(jiān)聽,如下:
process.on("rejectionHandled", p => { console.log("It has been handled") }) process.on("unhandledRejection", (reason, p) => { console.log("Went here") }) let test = new Promise((resolve, reject) => { let err = new Error("Just for a test") err.name = "TestError" reject(err) }) setTimeout(() => { test.catch(err => { console.log("Excample work!") console.log(err) }) }, 10000) // 打印出來的信息順序是: // Went here // It has been handled // Excample work! // { TestError: Just for a test // ....(stack message here) }
(承上)
uncaughtException
????其余 js 運(yùn)行中發(fā)生 || 拋出的未捕獲錯(cuò)誤,均可通過監(jiān)聽該事件解決,若不進(jìn)行該事件的監(jiān)聽,發(fā)生異常時(shí),會(huì)直接導(dǎo)致程序 crash
????但不建議用這種方式 catch,程序運(yùn)行中的錯(cuò)誤 更應(yīng)該是拋出來,所有的 error 都 catch 的話,豈不是程序都可以看成無 bug 了
????but 在打錯(cuò)誤日志的時(shí)候是需要 catch 上報(bào)日志的,但是在上報(bào)完后,需要繼續(xù)把 error throw,對于 uncaughtException callback 中拋出的異常不會(huì)再捕獲,而是以非 0 的狀態(tài)碼 exit
// Promise Rejection process.on("unhandledRejection", err => { process.nextTick(() => { throw err })) }) // 終極 boss process.on("uncaughtException", err => {...}) };四.小結(jié)
五. 源碼解讀以上以一張圖為總結(jié):
補(bǔ)充之前沒補(bǔ)充完的內(nèi)容,下圖為 node 中對于 process 的初始化等系列流程
node.cc 其實(shí)是 node 運(yùn)行主要的文件,其中定義了三個(gè)重載函數(shù) Start,調(diào)用順序?yàn)?3 → 2 → 1,每個(gè)函數(shù)參數(shù)不同處理不同的邏輯;
isolate->AddMessageListener 的監(jiān)聽事件 OnMessage 會(huì)在 js 運(yùn)行發(fā)生錯(cuò)誤時(shí)觸發(fā),嗯,是的,只有 error 才會(huì)傳遞 ;這很好的解釋了為什么 process 監(jiān)聽 uncaughtException 就可以監(jiān)聽到所有的拋出的非 promise 異常;
OnMessage 調(diào)用了 FatalException 函數(shù),F(xiàn)atalException 引用 process._fatalException 并傳入 error (env 是 env.h 中聲明的 Environment 類實(shí)例,fatal_exception_string 也是其中定義的,返回值為 "_fatalException");
以下為 FatalException 函數(shù)的部分內(nèi)容
void FatalException(Isolate* isolate, Localerror, Local message) { ...(省略) Local fatal_exception_string = env->fatal_exception_string(); // "_fatalException" Local fatal_exception_function = process_object->Get(fatal_exception_string).As (); ...(省略) if (exit_code == 0) { TryCatch fatal_try_catch(isolate); // 調(diào)用 v8::TryCatch // Do not call FatalException when _fatalException handler throws fatal_try_catch.SetVerbose(false); // 關(guān)鍵點(diǎn) // this will return true if the JS layer handled it, false otherwise Local caught = fatal_exception_function->Call(process_object, 1, &error); // 運(yùn)行 process._fatalException 函數(shù) if (fatal_try_catch.HasCaught()) { // 捕獲錯(cuò)誤 // the fatal exception function threw, so we must exit ReportException(env, fatal_try_catch); exit_code = 7; } if (exit_code == 0 && false == caught->BooleanValue()) { ReportException(env, error, message); exit_code = 1; } } ...(省略) }
六. END在調(diào)用 _fatalException 函數(shù)前,先調(diào)用 v8::TryCatch::setVerbose 把 verbose 設(shè)置為 false,則運(yùn)行時(shí)拋出的異常就不會(huì)再觸發(fā) FatalException ;在捕獲到運(yùn)行錯(cuò)誤后,把 exit_code 設(shè)為 7,并返回;這就解釋了 為什么在 uncaughtException 時(shí)拋出的異常不會(huì)再重新觸發(fā)回調(diào),要知道 EventEmitter 可沒幫你做這樣的事情
_fatalException 在觸發(fā) "uncaughtException" 事件前其實(shí)是會(huì)優(yōu)先檢查 domain 是否存在,當(dāng) domain 不存在時(shí)才會(huì)調(diào)用 uncaughtException 的,但 domain 這個(gè) api 已經(jīng)被廢除了,也就不累述了
unhandledRejection 事件的觸發(fā)整體思路也差不多,首先會(huì)調(diào)用 SetupPromises 初始化,然后調(diào)用 v8::Isolate::SetPromiseRejectCallback 進(jìn)行監(jiān)聽 ... 并且跟 uncaughtException 不同的是 unhandledRejection 的觸發(fā)只會(huì)打印 warning 并不會(huì)把整個(gè)程序給 crash 了
若本文有誤,歡迎隨時(shí)指正
參考鏈接
V8 API Reference Guide
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/91927.html
摘要:本文主要關(guān)注的是接口測試。所謂接口測試,就是檢查系統(tǒng)提供的接口是否符合事先撰寫的接口文檔。作為接口測試的解決方案,我們必須具備通用性與易用性。 開始 最近幾年,前端測試漸漸被人重視,相關(guān)的框架和方法已經(jīng)比較成熟。斷言庫有should, expect, chai。 單元測試框架有mocha, jasmine, Qunit。 模擬瀏覽器測試環(huán)境有Phantomjs, Slimerjs。 集...
摘要:本文主要關(guān)注的是接口測試。所謂接口測試,就是檢查系統(tǒng)提供的接口是否符合事先撰寫的接口文檔。作為接口測試的解決方案,我們必須具備通用性與易用性。 開始 最近幾年,前端測試漸漸被人重視,相關(guān)的框架和方法已經(jīng)比較成熟。斷言庫有should, expect, chai。 單元測試框架有mocha, jasmine, Qunit。 模擬瀏覽器測試環(huán)境有Phantomjs, Slimerjs。 集...
摘要:由于這種特性,某一個(gè)任務(wù)的后續(xù)操作,往往采用回調(diào)函數(shù)的形式進(jìn)行定義。另外,回調(diào)函數(shù)本身的第一個(gè)參數(shù),約定為上一步傳入的錯(cuò)誤對象。這種寫法有一個(gè)很大的好處,就是說只要判斷回調(diào)函數(shù)的第一個(gè)參數(shù),就知道有沒有出錯(cuò),如果不是,就肯定出錯(cuò)了。 REPL環(huán)境 在命令行鍵入node命令,后面沒有文件名,就進(jìn)入一個(gè)Node.js的REPL環(huán)境(Read–eval–print loop,讀取-求值-輸出...
摘要:個(gè)人博客原文迪米特法則設(shè)計(jì)模式六大原則之五迪米特法則。老師便給同學(xué)們講解了這個(gè)例子,讓學(xué)生感受一番迪米特法則。總結(jié)迪米特法則主要講述的觀點(diǎn)是高內(nèi)聚低耦合。 個(gè)人博客原文:迪米特法則 showImg(https://segmentfault.com/img/remote/1460000017779272?w=960&h=520); 設(shè)計(jì)模式六大原則之五:迪米特法則。 簡介 姓名:迪米特法...
摘要:將品牌的標(biāo)價(jià)全部加蘇南的專欄交流公眾號(hào)不會(huì)對空數(shù)組進(jìn)行檢測。方法用于調(diào)用數(shù)組的每個(gè)元素,并將元素傳遞給回調(diào)函數(shù)。 showImg(https://segmentfault.com/img/bVblSSO?w=1008&h=298); 前言: ? 今天我想分享一個(gè)有關(guān)于循環(huán)篩選的知識(shí)點(diǎn),也許是前端小白的你首先想到的是用for循環(huán)做篩選,但我這種小菜鳥想到的就是map(工作中很喜歡...
閱讀 2854·2023-04-25 17:59
閱讀 685·2023-04-25 15:05
閱讀 674·2021-11-25 09:43
閱讀 3036·2021-10-12 10:13
閱讀 3540·2021-09-27 13:59
閱讀 3587·2021-09-23 11:21
閱讀 3884·2021-09-08 09:35
閱讀 569·2019-08-29 17:12