国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Node 錯誤處理之挖坑系列

afishhhhh / 1935人閱讀

摘要:一中的對象包含了錯誤的具體信息,包括錯誤堆棧等。不源碼了,特別簡單,自己去一下。

一. Error

????JS 中的 Error 對象. 包含了錯誤的具體信息,包括 name、message、錯誤堆棧 stack 等??梢砸?new Error 方式創建實例拋出,或調用 Error.captureStackTrace 為已有對象添加 stack 錯誤堆棧信息 而后拋出

二. 錯誤拋出幾種方式

Throw
Javascript 拋出的異常,是以 throw 方法拋出,未必都是 Error 的實例,但通過 nodeJs 或者 js 運行時發生的錯誤,都是 Error 的實例

EventEmitter
Nodejs 形式的錯誤回調,大部分流 & 異步事件都衍生自 EventEmitter 類 || 實例,如 fs, process, stream 等

Process
程序運行過程中拋出的異常,或由底層庫拋出,或是運行中發生的一些 SyntaxError 之類

三. 錯誤捕獲幾種方式

try .. catch

常用的一種捕獲錯誤方式,瀏覽器 || node 環境均適用

缺點:只針對同步異常有效

    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() 發布事件,但會有最大的 maxListener 的限制,可更改。
????不 show 源碼了,特別簡單,自己去 look 一下。如 koa 的 app 就是基于 EventEmitter 的擴展,因此可以通過監聽 error

    class Koa extends EventEmitter {...}
    
    let app = new Koa()
    app.emit("error", ..)
    app.on("error", ...)

Process

Process 進程對象也是 EventEmitter 的實例,可通過如下兩事件監聽 error

unhandledRejection
????promise 的回調報錯,可通過監聽該事件 catch,但要注意由于 promise 的 rejection catched 不知道會在啥時候才發生,所以實際上可能在 unhandledRejection 事件觸發后才 catch 了這個信息,對應有 rejectionHandled 事件監聽,如下:

    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 運行中發生 || 拋出的未捕獲錯誤,均可通過監聽該事件解決,若不進行該事件的監聽,發生異常時,會直接導致程序 crash
????但不建議用這種方式 catch,程序運行中的錯誤 更應該是拋出來,所有的 error 都 catch 的話,豈不是程序都可以看成無 bug 了
????but 在打錯誤日志的時候是需要 catch 上報日志的,但是在上報完后,需要繼續把 error throw,對于 uncaughtException callback 中拋出的異常不會再捕獲,而是以非 0 的狀態碼 exit

    // Promise Rejection
    process.on("unhandledRejection", err => {
        process.nextTick(() => { throw err }))
    })
    // 終極 boss
    process.on("uncaughtException", err => {...})
};
四.小結

以上以一張圖為總結:

五. 源碼解讀

補充之前沒補充完的內容,下圖為 node 中對于 process 的初始化等系列流程

node.cc 其實是 node 運行主要的文件,其中定義了三個重載函數 Start,調用順序為 3 → 2 → 1,每個函數參數不同處理不同的邏輯;

isolate->AddMessageListener 的監聽事件 OnMessage 會在 js 運行發生錯誤時觸發,嗯,是的,只有 error 才會傳遞 ;這很好的解釋了為什么 process 監聽 uncaughtException 就可以監聽到所有的拋出的非 promise 異常;

OnMessage 調用了 FatalException 函數,FatalException 引用 process._fatalException 并傳入 error (env 是 env.h 中聲明的 Environment 類實例,fatal_exception_string 也是其中定義的,返回值為 "_fatalException");
以下為 FatalException 函數的部分內容

void FatalException(Isolate* isolate,
                    Local error,
                    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); // 調用 v8::TryCatch 
    
    // Do not call FatalException when _fatalException handler throws
    fatal_try_catch.SetVerbose(false); // 關鍵點

    // this will return true if the JS layer handled it, false otherwise
    Local caught =
        fatal_exception_function->Call(process_object, 1, &error); // 運行 process._fatalException 函數

    if (fatal_try_catch.HasCaught()) { // 捕獲錯誤
      // 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;
    }
  }
...(省略)
}

在調用 _fatalException 函數前,先調用 v8::TryCatch::setVerbose 把 verbose 設置為 false,則運行時拋出的異常就不會再觸發 FatalException ;在捕獲到運行錯誤后,把 exit_code 設為 7,并返回;這就解釋了 為什么在 uncaughtException 時拋出的異常不會再重新觸發回調,要知道 EventEmitter 可沒幫你做這樣的事情

_fatalException 在觸發 "uncaughtException" 事件前其實是會優先檢查 domain 是否存在,當 domain 不存在時才會調用 uncaughtException 的,但 domain 這個 api 已經被廢除了,也就不累述了

unhandledRejection 事件的觸發整體思路也差不多,首先會調用 SetupPromises 初始化,然后調用 v8::Isolate::SetPromiseRejectCallback 進行監聽 ... 并且跟 uncaughtException 不同的是 unhandledRejection 的觸發只會打印 warning 并不會把整個程序給 crash 了

六. END

若本文有誤,歡迎隨時指正

參考鏈接
V8 API Reference Guide

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/91927.html

相關文章

  • 關于前端接口測試的探索和挖坑

    摘要:本文主要關注的是接口測試。所謂接口測試,就是檢查系統提供的接口是否符合事先撰寫的接口文檔。作為接口測試的解決方案,我們必須具備通用性與易用性。 開始 最近幾年,前端測試漸漸被人重視,相關的框架和方法已經比較成熟。斷言庫有should, expect, chai。 單元測試框架有mocha, jasmine, Qunit。 模擬瀏覽器測試環境有Phantomjs, Slimerjs。 集...

    Crazy_Coder 評論0 收藏0
  • 關于前端接口測試的探索和挖坑

    摘要:本文主要關注的是接口測試。所謂接口測試,就是檢查系統提供的接口是否符合事先撰寫的接口文檔。作為接口測試的解決方案,我們必須具備通用性與易用性。 開始 最近幾年,前端測試漸漸被人重視,相關的框架和方法已經比較成熟。斷言庫有should, expect, chai。 單元測試框架有mocha, jasmine, Qunit。 模擬瀏覽器測試環境有Phantomjs, Slimerjs。 集...

    zxhaaa 評論0 收藏0
  • node學習系列基礎(二)

    摘要:由于這種特性,某一個任務的后續操作,往往采用回調函數的形式進行定義。另外,回調函數本身的第一個參數,約定為上一步傳入的錯誤對象。這種寫法有一個很大的好處,就是說只要判斷回調函數的第一個參數,就知道有沒有出錯,如果不是,就肯定出錯了。 REPL環境 在命令行鍵入node命令,后面沒有文件名,就進入一個Node.js的REPL環境(Read–eval–print loop,讀取-求值-輸出...

    zhaot 評論0 收藏0
  • 迪米特法則

    摘要:個人博客原文迪米特法則設計模式六大原則之五迪米特法則。老師便給同學們講解了這個例子,讓學生感受一番迪米特法則。總結迪米特法則主要講述的觀點是高內聚低耦合。 個人博客原文:迪米特法則 showImg(https://segmentfault.com/img/remote/1460000017779272?w=960&h=520); 設計模式六大原則之五:迪米特法則。 簡介 姓名:迪米特法...

    OnlyMyRailgun 評論0 收藏0
  • 深入了解JavaScript 中的For循環詳解

    摘要:將品牌的標價全部加蘇南的專欄交流公眾號不會對空數組進行檢測。方法用于調用數組的每個元素,并將元素傳遞給回調函數。 showImg(https://segmentfault.com/img/bVblSSO?w=1008&h=298); 前言: ? 今天我想分享一個有關于循環篩選的知識點,也許是前端小白的你首先想到的是用for循環做篩選,但我這種小菜鳥想到的就是map(工作中很喜歡...

    linkin 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<